diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644
index 000000000..21ca13352
--- /dev/null
+++ b/tools/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required( VERSION 2.8.7 )
+
+add_subdirectory( re2c )
+add_subdirectory( updaterevision )
+add_subdirectory( zipdir )
+
+set( CROSS_EXPORTS ${CROSS_EXPORTS} PARENT_SCOPE )
diff --git a/tools/re2c/CHANGELOG b/tools/re2c/CHANGELOG
new file mode 100644
index 000000000..02a523c27
--- /dev/null
+++ b/tools/re2c/CHANGELOG
@@ -0,0 +1,403 @@
+Version 0.16 (2016-01-21)
+---------------------------
+- Fixed bug #127 "code generation error with wide chars and bitmaps (omitted 'goto' statement)"
+- Added DFA minimization and option '--dfa-minimization
'
+- Fixed bug #128 "very slow DFA construction (resulting in a very large DFA)"
+- Fixed bug #132 "test failure on big endian archs with 0.15.3"
+
+Version 0.15.3 (2015-12-02)
+---------------------------
+- Fixed bugs and applied patches:
+ #122 "clang does not compile re2c 0.15.x" (reported and fixed by Oleksii Taran).
+ #124 "Get rid of UINT32_MAX and friends" (patch by Sergei Trofimovich, fixes FreeBSD builds).
+ #125 "[OS X] git reports changes not staged for commit in newly cloned repository" (by Oleksii Taran, this fix also applies to Windows).
+- Added option --no-version that allows to omit version information.
+- Reduced memory and time consumed with -Wundefined-control-flow.
+- Improved coverage of input data generated with -S --skeleton.
+
+Version 0.15.2 (2015-11-23)
+---------------------------
+- Fixed build system: lexer depends on bison-generated parser
+ (Gentoo bug: https://bugs.gentoo.org/show_bug.cgi?id=566620)
+
+Version 0.15.1 (2015-11-22)
+---------------------------
+- Fixed test failures caused by locale-sensitive 'sort'.
+
+Version 0.15 (2015-11-22)
+-------------------------
+- Updated website http://re2c.org:
+ added examples
+ updated docs
+ added news
+ added web feed (Atom 1.0)
+- Added options:
+ -S, --skeleton
+ --empty-class
+- Added warnings:
+ -W
+ -Werror
+ -W
+ -Wno-
+ -Werror-
+ -Wno-error-
+- Added individual warnings:
+ -Wundefined-control-flow
+ -Wunreachable-rules
+ -Wcondition-order
+ -Wuseless-escape
+ -Wempty-character-class
+ -Wswapped-range
+ -Wmatch-empty-string
+- Fixed options:
+ -- (interpret remaining arguments as non-options)
+- Deprecated options:
+ -1 --single-pass (single pass is by default now)
+- Reduced size of the generated .dot files.
+- Fixed bugs:
+ #27 re2c crashes reading files containing %{ %} (patch by Rui)
+ #51 default rule doesn't work in reuse mode
+ #52 eliminate multiple passes
+ #59 bogus yyaccept in -c mode
+ #60 redundant use of YYMARKER
+ #61 empty character class [] matches empty string
+ #115 flex-style named definitions cause ambiguity in re2c grammar
+ #119 -f with -b/-g generates incorrect dispatch on fill labels
+ #116 empty string with non-empty trailing context consumes code units
+- Added test options:
+ -j, -j (run tests in N threads, defaults to the number of CPUs)
+ --wine (test windows builds using wine)
+ --skeleton (generate skeleton programs, compile and execute them)
+ --keep-tmp-files (don't delete intermediate files for successful tests)
+- Updated build system:
+ support out of source builds
+ support `make distcheck`
+ added `make bootstrap` (rebuild re2c after building with precomplied .re files)
+ added `make tests` (run tests with -j)
+ added `make vtests` (run tests with --valgrind -j)
+ added `make wtests` (run tests with --wine -j 1)
+ added Autoconf tests for CXXFLAGS. By default try the following options:
+ -W -Wall -Wextra -Weffc++ -pedantic -Wformat=2 -Wredundant-decls
+ -Wsuggest-attribute=format -Wconversion -Wsign-conversion -O2 -Weverything),
+ respect user-defined CXXFLAGS
+ support Mingw builds: `configure -host i686-w64-mingw32`
+ structured source files
+ removed old MSVC files
+- Moved development to github (https://github.com/skvadrik/re2c), keep a mirror on sourceforge.
+
+Version 0.14.3 (2015-05-20)
+-----------------------------
+- applied patch '#27 re2c crashes reading files containing %{ %}' by Rui
+- dropped distfiles for MSVC (they are broken anyway)
+
+Version 0.14.2 (2015-03-25)
+-----------------------------
+- fixed #57 Wrong result only if another rule is present
+
+Version 0.14.1 (2015-02-27)
+-----------------------------
+- fixed #55 re2c-0.14: re2c -V outputs null byte
+
+Version 0.14 (2015-02-23)
+-----------------------------
+- Added generic input API 21 (#21 Support to configure how re2c code interfaced with the symbol buffer?)
+- fixed #46 re2c generates an infinite loop, depends on existence of previous parser
+- fixed #47 Dot output label escaped characters
+
+Version 0.13.7.5 (2014-08-22)
+-----------------------------
+- Fixed Gentoo bug: https://bugs.gentoo.org/show_bug.cgi?id=518904 (PHP lexer)
+
+Version 0.13.7.4 (2014-07-29)
+-----------------------------
+- Enabled 'make docs' only if configured with '--enable-docs'
+- Disallowed to use yacc/byacc instead of bison to build parser
+- Removed non-portable sed feature in script that runs tests
+
+Version 0.13.7.3 (2014-07-28)
+-----------------------------
+- Fixed CXX warning
+- Got rid of asciidoc build-time dependency
+
+Version 0.13.7.2 (2014-07-27)
+-----------------------------
+- Included man page into dist, respect users CXXFLAGS.
+
+Version 0.13.7.1 (2014-07-26)
+-----------------------------
+- Added missing files to tarball
+
+Version 0.13.7 (2014-07-25)
+---------------------------
+- Added UTF-8 support
+- Added UTF-16 support
+- Added default rule
+- Added option to control ill-formed Unicode
+
+Version 0.13.6 (2013-07-04)
+---------------------------
+- Fixed #2535084 uint problem with Sun C 5.8
+- #3308400: allow Yacc-style %{code brackets}%
+- #2506253: allow C++ // comments
+- Fixed inplace configuration in -e mode.
+- Applied #2482572 Typos in error messages.
+- Applied #2482561 Error in manual section on -r mode.
+- Fixed #2478216 Wrong start_label in -c mode.
+- Fixed #2186718 Unescaped backslash in file name of #line directive.
+- Fixed #2102138 Duplicate case labels on EBCDIC.
+- Fixed #2088583 Compile problem on AIX.
+- Fixed #2038610 Ebcdic problem.
+- improve dot support: make char intervals (e.g. [A-Z]) instead of one edge per char
+
+Version 0.13.5 (2008-05-25)
+---------------------------
+- Fixed #1952896 Segfault in re2c::Scanner::scan.
+- Fixed #1952842 Regression.
+
+Version 0.13.4 (2008-04-05)
+---------------------------
+- Added transparent handling of #line directives in input files.
+- Added re2c:yyfill:check inplace configuration.
+- Added re2c:define:YYSETSTATE:naked inplace configuration.
+- Added re2c:flags:w and re2c:flags:u inplace configurations.
+- Added the ability to add rules in 'use:re2c' blocks.
+- Changed -r flag to accept only 'rules:re2c' and 'use:re2c' blocks.
+
+Version 0.13.3 (2008-03-14)
+---------------------------
+- Added -r flag to allow reuse of scanner definitions.
+- Added -F flag to support flex syntax in rules.
+- Fixed SEGV in scanner that occurs with very large blocks.
+- Fixed issue with unused yybm.
+- Partial support for flex syntax.
+- Changed to allow /* comments with -c switch.
+- Added flag -D/--emit-dot.
+
+Version 0.13.2 (2008-02-14)
+---------------------------
+- Added flag --case-inverted.
+- Added flag --case-insensitive.
+- Added support for '' to enable rule setup.
+- Added support for '=>' style rules.
+- Added support for ':=' style rules.
+- Added support for ':=>' style rules.
+- Added re2c:cond:divider and re2c:con:goto inplace configuration.
+- Fixed code generation to emit space after 'if'.
+
+Version 0.13.1 (2007-08-24)
+---------------------------
+- Added custom build rules for Visual Studio 2005 (re2c.rules). (William Swanson)
+- Fixed issue with some compilers.
+- Fixed #1776177 Build on AIX.
+- Fixed #1743180 fwrite with 0 length crashes on OS X.
+
+Version 0.13.0 (2007-06-24)
+---------------------------
+- Added -c and -t to generate scanners with (f)lex-like condition support.
+- Fixed issue with short form of switches and parameter if not first switch.
+- Fixed #1708378 segfault in actions.cc.
+
+Version 0.12.3 (2007-08-24)
+---------------------------
+- Fixed issue with some compilers.
+- Fixed #1776177 Build on AIX.
+- Fixed #1743180 fwrite with 0 length crashes on OS X.
+
+Version 0.12.2 (2007-06-26)
+---------------------------
+- Fixed #1743180 fwrite with 0 length crashes on OS X.
+
+Version 0.12.1 (2007-05-23)
+---------------------------
+- Fixed #1711240 problem with '"' and 7F on EBCDIC plattforms.
+
+Version 0.12.0 (2007-05-01)
+---------------------------
+- Re-release of 0.11.3 as new stable branch.
+- Fixed issue with short form of switches and parameter if not first switch.
+- Fixed #1708378 segfault in actions.cc.
+
+Version 0.11.3 (2007-04-01)
+---------------------------
+- Added support for underscores in named definitions.
+- Added new option --no-generation-date.
+- Fixed issue with long form of switches.
+
+Version 0.11.2 (2007-03-01)
+---------------------------
+- Added inplace configuration 're2c:yyfill:parameter'.
+- Added inplace configuration 're2c:yych:conversion'.
+- Fixed -u switch code generation.
+- Added ability to avoid defines and overwrite variable and label names.
+
+Version 0.11.1 (2007-02-20)
+---------------------------
+- Applied #1647875 add const to yybm vector.
+
+Version 0.11.0 (2007-01-01)
+---------------------------
+- Added -u switch to support unicode.
+
+Version 0.10.8 (2007-04-01)
+---------------------------
+- Fixed issue with long form of switches.
+
+Version 0.10.7 (2007-02-20)
+---------------------------
+- Applied #1647875 add const to yybm vector.
+
+Version 0.10.6 (2006-08-05)
+---------------------------
+- Fixed #1529351 Segv bug on unterminated code blocks.
+- Fixed #1528269 Invalid code generation.
+
+Version 0.10.5 (2006-06-11)
+---------------------------
+- Fixed long form of -1 switch to --single-pass as noted in man page and help.
+- Added MSVC 2003 project files and renamed old 2002 ones.
+
+Version 0.10.4 (2006-06-01)
+---------------------------
+- Fix whitespace in generated code.
+
+Version 0.10.3 (2006-05-14)
+---------------------------
+- Fixed issue with -wb and -ws.
+- Added -g switch to support gcc's computed goto's.
+- Changed to use nested if's instead of "switch(yyaccept)" in -s mode.
+
+Version 0.10.2 (2006-05-01)
+---------------------------
+- Changed to generate YYMARKER only when needed or in single pass mode.
+- Added -1 switch to force single pass generation and make two pass the default.
+- Fixed -i switch.
+- Added configuration 'yyfill:enable' to allow suppression of YYFILL() blocks.
+- Added tutorial like lessons to re2c.
+- Added /*!ignore:re2c */ to support documenting of re2c source.
+- Fixed issue with multiline re2c comments (/*!max:re2c ... */ and alike).
+- Fixed generation of YYDEBUG() when using -d switch.
+- Added /*!getstate:re2c */ which triggers generation of the YYGETSTATE() block.
+- Added configuration 'state:abort'.
+- Changed to not generate yyNext unless configuration 'state:nextlabel' is used.
+- Changed to not generate yyaccept code unless needed.
+- Changed to use if- instead of switch-expression when yyaccpt has only one case.
+- Added docu, examples and tests to .src.zip package (0.10.1 zip was repackaged).
+- Fixed #1479044 incorrect code generated when using -b.
+- Fixed #1472770 re2c creates an infinite loop.
+- Fixed #1454253 Piece of code saving a backtracking point not generated.
+- Fixed #1463639 Missing forward declaration.
+- Implemented #1187127 savable state support for multiple re2c blocks.
+
+Version 0.10.1 (2006-02-28)
+---------------------------
+- Added support for Solaris and native SUN compiler.
+- Applied #1438160 expose YYCTXMARKER.
+
+Version 0.10.0 (2006-02-18)
+---------------------------
+- Added make target zip to create windows source packages as zip files.
+- Added re2c:startlabel configuration.
+- Fixed code generation to not generate unreachable code for initial state.
+- Added support for c/c++ compatible \u and \U unicode notation.
+- Added ability to control indendation.
+- Made scanner error out in case an ambiguous /* is found.
+- Fixed indendation of generated code.
+- Added support for DOS line endings.
+- Added experimental unicode support.
+- Added config_w32.h to build out of the box on windows (using msvc 2002+).
+- Added Microsoft Visual C .NET 2005 build files.
+- Applied #1411087 variable length trailing context.
+- Applied #1408326 do not generate goto next state.
+- Applied #1408282 CharSet initialization fix.
+- Applied #1408278 readsome with MSVC.
+- Applied #1307467 Unicode patch for 0.9.7.
+
+Version 0.9.12 (2005-12-28)
+---------------------------
+- Fixed bug #1390174 re2c cannot accept {0,}.
+
+Version 0.9.11 (2005-12-18)
+---------------------------
+- Fixed #1313083 -e (EBCDIC cross compile) broken.
+- Fixed #1297658 underestimation of n in YYFILL(n).
+- Applied #1339483 Avoid rebuilds of re2c when running subtargets.
+- Implemented #1335305 symbol table reimplementation, just slightly modifed.
+
+Version 0.9.10 (2005-09-04)
+---------------------------
+- Added -i switch to avoid generating #line information.
+- Fixed bug #1251653 re2c generate some invalid #line on WIN32.
+
+Version 0.9.9 (2005-07-21)
+--------------------------
+- Implemented #1232777 negated char classes '[^...]' and the dot operator '.'.
+- Added hexadecimal character definitions.
+- Added consistency check for octal character definitions.
+
+Version 0.9.8 (2005-06-26)
+--------------------------
+- Fixed code generation for -b switch.
+- Added Microsoft Visual C .NET build files.
+
+Version 0.9.7 (2005-04-30)
+--------------------------
+- Applied #1181535 storable state patch.
+- Added -d flag which outputs a debugable parser.
+- Fixed generation of '#line' directives (according to ISO-C99).
+- Fixed bug #1187785 Re2c fails to generate valid code.
+- Fixed bug #1187452 unused variable `yyaccept'.
+
+Version 0.9.6 (2005-04-14)
+--------------------------
+- Fixed build with gcc >= 3.4.
+
+Version 0.9.5 (2005-04-08)
+--------------------------
+- Added /*!max:re2c */ which emits a '#define YYMAXFILL \n' line
+ This allows to define buffers of the minimum required length. Occurence
+ must follow '/*re2c */ and cannot preceed it.
+- Changed re2c to two pass generation to output warning free code.
+- Fixed bug #1163046 re2c hangs when processing valid re-file.
+- Fixed bug #1022799 re2c scanner has buffering bug.
+
+Version 0.9.4 (2005-03-12)
+--------------------------
+- Added --vernum support.
+- Fixed bug #1054496 incorrect code generated with -b option.
+- Fixed bug #1012748 re2c does not emit last line if '\n' missing.
+- Fixed bug #999104 --output=output option does not work as documented.
+- Fixed bug #999103 Invalid options prefixed with two dashes cause program crash.
+
+Version 0.9.3 (2004-05-26)
+--------------------------
+- Fixes one small possible bug in the generated output. ych instead of yych is
+ output in certain circumstances
+
+Version 0.9.2 (2004-05-26)
+--------------------------
+- Added -o option to specify the output file which also will set the #line
+ directives to something useful.
+- Print version to cout instead cerr.
+- Added -h and -- style options.
+- Moved development to http://sourceforge.net/projects/re2c .
+- Fixed bug #960144 minor cosmetic problem.
+- Fixed bug #953181 cannot compile with.
+- Fixed bug #939277 Windows support.
+- Fixed bug #914462 automake build patch
+- Fixed bug #891940 braced quantifiers: {\d+(,|,\d+)?} style.
+- Fixed bug #869298 Add case insensitive string literals.
+- Fixed bug #869297 Input buffer overrun.
+
+Version 0.9.1 (2003-12-13)
+--------------------------
+- Removed rcs comments in source files.
+
+Version 0.9
+-----------
+- Redistribution based on version 0.5.
+- Added parentheses to assignment expressions in 'if' statements.
+- Rearranged class members to match initialization order.
+- Substr fix.
+- Use array delete [] when necessary.
+- Other minor fixes for subduing compiler warnings.
+
diff --git a/tools/re2c/CMakeLists.txt b/tools/re2c/CMakeLists.txt
new file mode 100644
index 000000000..b362a3b84
--- /dev/null
+++ b/tools/re2c/CMakeLists.txt
@@ -0,0 +1,104 @@
+cmake_minimum_required( VERSION 2.8.7 )
+
+if( NOT CMAKE_CROSSCOMPILING )
+
+include( CheckFunctionExists )
+include( CheckTypeSize )
+
+if( MSVC )
+ # Runtime type information is required and don't complain about uint32_t to bool conversions
+ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR /wd4800" )
+endif()
+
+set( PACKAGE_NAME re2c )
+set( PACKAGE_TARNAME re2c )
+set( PACKAGE_VERSION 0.16 )
+set( PACKAGE_STRING "re2c 0.16" )
+set( PACKAGE_BUGREPORT "re2c-general@lists.sourceforge.net" )
+
+CHECK_FUNCTION_EXISTS( strdup HAVE_STRDUP )
+CHECK_FUNCTION_EXISTS( strndup HAVE_STRNDUP )
+
+CHECK_TYPE_SIZE( "0i8" SIZEOF_0I8 )
+CHECK_TYPE_SIZE( "0l" SIZEOF_0L )
+CHECK_TYPE_SIZE( "0ll" SIZEOF_0LL )
+CHECK_TYPE_SIZE( char SIZEOF_CHAR )
+CHECK_TYPE_SIZE( short SIZEOF_SHORT )
+CHECK_TYPE_SIZE( int SIZEOF_INT )
+CHECK_TYPE_SIZE( long SIZEOF_LONG )
+CHECK_TYPE_SIZE( "long long" SIZEOF_LONG_LONG )
+CHECK_TYPE_SIZE( "void *" SIZEOF_VOID_P )
+CHECK_TYPE_SIZE( __int64 SIZEOF___INT_64 )
+
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h )
+include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} )
+add_definitions( -DHAVE_CONFIG_H )
+
+file( GLOB SRC_HDR
+ src/codegen/*.h
+ src/conf/*.h
+ src/ir/*.h
+ src/*.h
+ src/parse/*.h
+ src/util/*.h )
+
+add_executable( re2c
+ ${SRC_HDR}
+ src/codegen/bitmap.cc
+ src/codegen/emit_action.cc
+ src/codegen/emit_dfa.cc
+ src/codegen/label.cc
+ src/codegen/go_construct.cc
+ src/codegen/go_destruct.cc
+ src/codegen/go_emit.cc
+ src/codegen/go_used_labels.cc
+ src/codegen/input_api.cc
+ src/codegen/output.cc
+ src/codegen/print.cc
+ src/conf/msg.cc
+ src/conf/opt.cc
+ src/conf/parse_opts.cc
+ src/conf/warn.cc
+ src/ir/nfa/calc_size.cc
+ src/ir/nfa/nfa.cc
+ src/ir/nfa/split.cc
+ src/ir/adfa/adfa.cc
+ src/ir/adfa/prepare.cc
+ src/ir/dfa/determinization.cc
+ src/ir/dfa/fillpoints.cc
+ src/ir/dfa/minimization.cc
+ src/ir/regexp/display.cc
+ src/ir/regexp/encoding/enc.cc
+ src/ir/regexp/encoding/range_suffix.cc
+ src/ir/regexp/encoding/utf8/utf8_regexp.cc
+ src/ir/regexp/encoding/utf8/utf8_range.cc
+ src/ir/regexp/encoding/utf8/utf8.cc
+ src/ir/regexp/encoding/utf16/utf16_regexp.cc
+ src/ir/regexp/encoding/utf16/utf16.cc
+ src/ir/regexp/encoding/utf16/utf16_range.cc
+ src/ir/regexp/fixed_length.cc
+ src/ir/regexp/regexp.cc
+ src/ir/compile.cc
+ src/ir/rule_rank.cc
+ src/ir/skeleton/control_flow.cc
+ src/ir/skeleton/generate_code.cc
+ src/ir/skeleton/generate_data.cc
+ src/ir/skeleton/match_empty.cc
+ src/ir/skeleton/maxlen.cc
+ src/ir/skeleton/skeleton.cc
+ src/ir/skeleton/unreachable.cc
+ src/ir/skeleton/way.cc
+ src/main.cc
+ src/parse/code.cc
+ src/parse/input.cc
+ src/parse/lex.cc
+ src/parse/lex_conf.cc
+ src/parse/parser.cc
+ src/parse/scanner.cc
+ src/parse/unescape.cc
+ src/util/s_to_n32_unsafe.cc
+ src/util/range.cc )
+
+set( CROSS_EXPORTS ${CROSS_EXPORTS} re2c PARENT_SCOPE )
+
+endif()
diff --git a/tools/re2c/NO_WARRANTY b/tools/re2c/NO_WARRANTY
new file mode 100644
index 000000000..885a13d06
--- /dev/null
+++ b/tools/re2c/NO_WARRANTY
@@ -0,0 +1,2 @@
+re2c is distributed with no warranty whatever. The author and any other
+contributors take no responsibility for the consequences of its use.
diff --git a/tools/re2c/README b/tools/re2c/README
new file mode 100644
index 000000000..29d97b674
--- /dev/null
+++ b/tools/re2c/README
@@ -0,0 +1,159 @@
+re2c
+--------------------------------------------------------------------------------
+
+
+DESCRIPTION
+--------------------------------------------------------------------------------
+re2c is a tool for generating C-based recognizers from regular expressions.
+re2c-based scanners are efficient: for programming languages, given similar
+specifications, a re2c-based scanner is typically almost twice as fast as a
+flex-based scanner with little or no increase in size (possibly a decrease
+on cisc architectures). Indeed, re2c-based scanners are quite competitive with
+hand-crafted ones.
+
+Unlike flex, re2c does not generate complete scanners: the user must supply some
+interface code. While this code is not bulky (about 50-100 lines for a
+flex-like scanner; see the man page and examples in the distribution) careful
+coding is required for efficiency (and correctness). One advantage of this
+arrangement is that the generated code is not tied to any particular input
+model.
+--------------------------------------------------------------------------------
+
+
+DOWNLOAD
+--------------------------------------------------------------------------------
+The re2c distribution can be found at:
+ https://sourceforge.net/projects/re2c/
+
+Download the latest tarball:
+ https://sourceforge.net/projects/re2c/files/latest/download
+
+Clone git repo:
+ git clone git://git.code.sf.net/p/re2c/code-git
+--------------------------------------------------------------------------------
+
+
+BUILD
+--------------------------------------------------------------------------------
+Contents:
+ 1. simple build
+ 2. bootstrap
+ 3. out-of-source build
+ 4. testing
+ 5. rebuild documentation
+ 6. build for windows with mingw
+ 7. build from git
+
+1. Simplest possible build:
+ $ ./configure [--prefix=]
+ $ make
+ $ make install
+This will build re2c and install it (binary and man page) to (defaults
+to /usr/local).
+
+2. Bootstrap and rebuild:
+ $ ./configure [--prefix=]
+ $ make bootstrap
+ $ make install
+Usual bootstrap procedure: re2c uses re2c to compile its lexer.
+1. build lexer (if make finds re2c binary in build directory, it will build lexer
+ from source, otherwize it will use prebuilt lexer)
+2. build re2c
+3. build lexer from source using re2c binary in build directory
+4. rebuild re2c
+
+3. Out-of-source build:
+ $ mkdir
+ $ cd
+ $ /configure [--prefix=]
+ $ make
+ $ make install
+
+4. Testing:
+ $ make check
+This will redirect test script output to file. If you want to see progress:
+ $ make tests
+Testing under valgrind (takes a long time):
+ $ make vtests
+
+5. Rebuild documentation (requires rst2man.py):
+ $ ./configure --enable-docs [--prefix=]
+ $ make docs
+ $ make install
+
+6. Build for windows using mingw:
+ $ ../configure --host i686-w64-mingw32 [--prefix=]
+ $ make
+This will result into an executable re2c.exe, which can be tested with wine:
+ $ make wtests
+
+7. If you want to build from git, you'll first need to generate autotools files:
+ $ ./autogen.sh
+--------------------------------------------------------------------------------
+
+
+INFO
+--------------------------------------------------------------------------------
+ $ man re2c
+
+re2c home page:
+ re2c.org
+
+re2c manual:
+ re2c.org/manual.html
+
+Ulya Trofimovich's blog on re2c:
+ skvadrik.github.io/aleph_null/re2c.html
+
+Original paper on re2c: "RE2C: a More Versatile Parser Generator" (1994, Peter
+Bumbulis and Donald D. Cowan).
+
+Examples can be found in 'examples' directory.
+--------------------------------------------------------------------------------
+
+
+MAILING LISTS
+--------------------------------------------------------------------------------
+re2c-general:
+ re2c-general@lists.sourceforge.net
+re2c-devel:
+ re2c-devel@lists.sourceforge.net
+
+You are welcome to ask for help or share your thoughts and ideas about re2c :)
+--------------------------------------------------------------------------------
+
+
+BUGS
+--------------------------------------------------------------------------------
+Please report any bugs and send feature requests to:
+ https://sourceforge.net/p/re2c/_list/tickets
+--------------------------------------------------------------------------------
+
+
+AUTHORS
+--------------------------------------------------------------------------------
+Originally written by Peter Bumbulis (peter@csg.uwaterloo.ca)
+Currently maintained by:
+ Ulya Trofimovich
+ Dan Nuffer
+ Marcus Boerger
+ Hartmut Kaiser
+--------------------------------------------------------------------------------
+
+
+LICENSE
+--------------------------------------------------------------------------------
+re2c is distributed with no warranty whatever. The code is certain to contain
+errors. Neither the author nor any contributor takes responsibility for any
+consequences of its use.
+
+re2c is in the public domain. The data structures and algorithms used in re2c
+are all either taken from documents available to the general public or are
+inventions of the authors. Programs generated by re2c may be distributed freely.
+re2c itself may be distributed freely, in source or binary, unchanged or
+modified. Distributors may charge whatever fees they can obtain for re2c.
+
+If you do make use of re2c, or incorporate it into a larger project an
+acknowledgement somewhere (documentation, research report, etc.) would be
+appreciated.
+--------------------------------------------------------------------------------
diff --git a/tools/re2c/config.h.in b/tools/re2c/config.h.in
new file mode 100644
index 000000000..38029b7cf
--- /dev/null
+++ b/tools/re2c/config.h.in
@@ -0,0 +1,58 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
+
+/* Name of package */
+#cmakedefine PACKAGE "@PACKAGE_NAME@"
+
+/* Define to the address where bug reports for this package should be sent. */
+#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
+
+/* Define to the full name of this package. */
+#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
+
+/* Define to the full name and version of this package. */
+#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
+
+/* Define to the one symbol short name of this package. */
+#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
+
+/* Define to the home page for this package. */
+#cmakedefine PACKAGE_URL "@PACKAGE_URL@"
+
+/* Define to the version of this package. */
+#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
+
+/* The size of `0i8', as computed by sizeof. */
+#cmakedefine SIZEOF_0I8 @SIZEOF_0I8@
+
+/* The size of `0l', as computed by sizeof. */
+#cmakedefine SIZEOF_0L @SIZEOF_0L@
+
+/* The size of `0ll', as computed by sizeof. */
+#cmakedefine SIZEOF_0LL @SIZEOF_0LL@
+
+/* The size of `char', as computed by sizeof. */
+#cmakedefine SIZEOF_CHAR @SIZEOF_CHAR@
+
+/* The size of `int', as computed by sizeof. */
+#cmakedefine SIZEOF_INT @SIZEOF_INT@
+
+/* The size of `long', as computed by sizeof. */
+#cmakedefine SIZEOF_LONG @SIZEOF_LONG@
+
+/* The size of `long long', as computed by sizeof. */
+#cmakedefine SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@
+
+/* The size of `short', as computed by sizeof. */
+#cmakedefine SIZEOF_SHORT @SIZEOF_SHORT@
+
+/* The size of `void *', as computed by sizeof. */
+#cmakedefine SIZEOF_VOID_P @SIZEOF_VOID_P@
+
+/* The size of `__int64', as computed by sizeof. */
+#cmakedefine SIZEOF___INT64 @SIZEOF___INT64@
+
+/* Version number of package */
+#cmakedefine VERSION @PACKAGE_VERSION@
diff --git a/tools/re2c/config.msc.h b/tools/re2c/config.msc.h
new file mode 100644
index 000000000..d64e6d9e9
--- /dev/null
+++ b/tools/re2c/config.msc.h
@@ -0,0 +1,62 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Name of package */
+/* #undef PACKAGE */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "re2c-general@lists.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "re2c"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "re2c 0.16"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "re2c"
+
+/* Define to the home page for this package. */
+/* #undef PACKAGE_URL */
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.16"
+
+/* The size of `0i8', as computed by sizeof. */
+#define SIZEOF_0I8 1
+
+/* The size of `0l', as computed by sizeof. */
+#define SIZEOF_0L 4
+
+/* The size of `0ll', as computed by sizeof. */
+#define SIZEOF_0LL 8
+
+/* The size of `char', as computed by sizeof. */
+#define SIZEOF_CHAR 1
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `void *', as computed by sizeof. */
+#ifdef _M_X64
+#define SIZEOF_VOID_P 8
+#else
+#define SIZEOF_VOID_P 4
+#endif
+
+/* The size of `__int64', as computed by sizeof. */
+#define SIZEOF___INT64 8
+
+/* Version number of package */
+/* #undef VERSION */
diff --git a/tools/re2c/examples/001_upn_calculator/README b/tools/re2c/examples/001_upn_calculator/README
new file mode 100644
index 000000000..81377d75a
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/README
@@ -0,0 +1,83 @@
+re2c lesson 001_upn_calculator, (c) M. Boerger 2006
+
+This lesson gets you started with re2c. In the end you will have an easy RPN
+(reverse polish notation) calculator for use at command line.
+
+You will learn about the basic interface of re2c when scanning input strings.
+How to detect the end of the input and use that to stop scanning in order to
+avoid problems.
+
+Once you have successfully installed re2c you can use it to generate *.c files
+from the *.re files presented in this lesson. Actually the expected *.c files
+are already present. So you should name them *.cc or something alike or just
+give them a different name like test.c. To do so you simply change into the
+directory and execute the following command:
+
+ re2c calc_001.re > test.c
+
+Then use your compiler to compile that code and run it. If you are using gcc
+you simply do the following:
+
+ gcc -o test.o test.c
+ ./test.o
+
+If you are using windows you might want to read till the end of this lesson.
+
+When you want to debug the code it helps to make re2c generate working #line
+information. To do so you simply specify the output file using the -o switch
+followed by the output filename:
+
+ re2c -o test.c calc_001.re
+
+The input files *.re each contain basic step by comments that explain what is
+going on and what you can see in the examples.
+
+In order to optimize the generated code we will use the -s command line switch
+of re2c. This tells re2c to generate code that uses if statements rather
+then endless switch/case expressions where appropriate. Note that the file name
+extension is actually '.s.re' to tell the test system to use the -s switch. To
+invoke re2 you do the following:
+
+ re2c -s -o test.c calc_006.s.re
+
+Finally we use the -b switch to have the code use a decision table. The -b
+switch also contains the -s behavior.
+
+ re2c -b -o test.c calc_007.b.re
+
+
+
+-------------------------------------------------------------------------------
+
+For windows users Lynn Allan provided some additional stuff to get you started
+in the Microsoft world. This addon resides in the windows subdirectory and
+gives you something to expereiment with. The code in that directory is based
+on the first step and has the following changes:
+
+* vc6 .dsp/.dsw and vc7/vc8 .sln/.vcproj project files that have "Custom Build
+Steps" that can tell when main.re changes, and know how to generate main.c
+from main.re. They assume that you unpacked the zip package and have re2c
+itself build or installed in Release and Release-2005 directory respectively.
+If re2c cannot be found you need to modify the custom build step and correct
+the path to re2c.
+
+* BuildAndRun.bat to do command line rec2 and then cl and then run the
+executable (discontinues with message if errors).
+
+* built-in cppunit-like test to confirm it worked as expected.
+
+* array of test strings "fed" to scan rather than file contents to facilitate
+testing and also reduce the newbie learning curve.
+
+* HiResTimer output for 10,000 loops and 100,000 loops. While this might be
+excessive for this lesson, it illustrates how to do it for subsequent lessons
+and your own stuff using windows. Also it shows that Release build is as fast
+as strncmp for this test and can probably be made significantly faster.
+
+* If you want to build the other steps of this lesson using windows tools
+simply copy the *.re files into the windows directory as main.re and rebuild.
+
+
+-------------------------------------------------------------------------------
+Sidenote: UPN is the german translation of RPN, somehow hardcoded into the
+authors brain :-)
diff --git a/tools/re2c/examples/001_upn_calculator/calc_001.re b/tools/re2c/examples/001_upn_calculator/calc_001.re
new file mode 100644
index 000000000..fe8d3ae1b
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_001.re
@@ -0,0 +1,84 @@
+/* re2c lesson 001_upn_calculator, calc_001, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- basic interface for string reading
+
+ . We define the macros YYCTYPE, YYCURSOR, YYLIMIT, YYMARKER, YYFILL
+ . YYCTYPE is the type re2c operates on or in other words the type that
+ it generates code for. While it is not a big difference when we were
+ using 'unsigned char' here we would need to run re2c with option -w
+ to fully support types with sieof() > 1.
+ . YYCURSOR is used internally and holds the current scanner position. In
+ expression handlers, the code blocks after re2c expressions, this can be
+ used to identify the end of the token.
+ . YYMARKER is not always being used so we set an initial value to avoid
+ a compiler warning. Here we could also omit it compleley.
+ . YYLIMIT stores the end of the input. Unfortunatley we have to use strlen()
+ in this lesson. In the next example we see one way to get rid of it.
+ . We use a 'for(;;)'-loop around the scanner block. We could have used a
+ 'while(1)'-loop instead but some compilers generate a warning for it.
+ . To make the output more readable we use 're2c:indent:top' scanner
+ configuration that configures re2c to prepend a single tab (the default)
+ to the beginning of each output line.
+ . The following lines are expressions and for each expression we output the
+ token name and continue the scanner loop.
+ . The second last token detects the end of our input, the terminating zero in
+ our input string. In other scanners detecting the end of input may vary.
+ For example binary code may contain \0 as valid input.
+ . The last expression accepts any input character. It tells re2c to accept
+ the opposit of the empty range. This includes numbers and our tokens but
+ as re2c goes from top to botton when evaluating the expressions this is no
+ problem.
+ . The first three rules show that re2c actually prioritizes the expressions
+ from top to bottom. Octal number require a starting "0" and the actual
+ number. Normal numbers start with a digit greater 0. And zero is finally a
+ special case. A single "0" is detected by the last rule of this set. And
+ valid ocal number is already being detected by the first rule. This even
+ includes multi "0" sequences that in octal notation also means zero.
+ Another way would be to only use two rules:
+ "0" [0-9]+
+ "0" | ( [1-9] [0-9]* )
+ A full description of re2c rule syntax can be found in the manual.
+*/
+
+#include
+#include
+#include
+
+int scan(char *s, int l)
+{
+ char *p = s;
+ char *q = 0;
+#define YYCTYPE char
+#define YYCURSOR p
+#define YYLIMIT (s+l)
+#define YYMARKER q
+#define YYFILL(n)
+
+ for(;;)
+ {
+/*!re2c
+ re2c:indent:top = 2;
+ "0"[0-9]+ { printf("Oct\n"); continue; }
+ [1-9][0-9]* { printf("Num\n"); continue; }
+ "0" { printf("Num\n"); continue; }
+ "+" { printf("+\n"); continue; }
+ "-" { printf("-\n"); continue; }
+ "\000" { printf("EOF\n"); return 0; }
+ [^] { printf("ERR\n"); return 1; }
+*/
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(argv[1], strlen(argv[1]));
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 1;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_002.re b/tools/re2c/examples/001_upn_calculator/calc_002.re
new file mode 100644
index 000000000..417e9f315
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_002.re
@@ -0,0 +1,69 @@
+/* re2c lesson 001_upn_calculator, calc_002, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- making use of YYFILL
+
+ . Here we modified the scanner to not require strlen() on the call. Instead
+ we compute limit on the fly. That is whenever more input is needed we
+ search for the terminating \0 in the next n chars the scanner needs.
+ . If there is not enough input we quit the scanner.
+ . Note that in lesson_001 YYLIMIT was a character pointer computed only once.
+ Here is of course also of type YYCTYPE but a variable that gets reevaluated
+ by YYFILL().
+ . To make the code smaller we take advantage of the fact that our loop has no
+ break so far. This allows us to use break here and have the code that is
+ used for YYFILL() not contain the printf in every occurence. That way the
+ generated code gets smaller.
+
+*/
+
+#include
+#include
+#include
+
+int fill(char *p, int n, char **l)
+{
+ while (*++p && n--) ;
+ * l = p;
+ return n <= 0;
+}
+
+int scan(char *s)
+{
+ char *p = s;
+ char *l = s;
+ char *q = 0;
+#define YYCTYPE char
+#define YYCURSOR p
+#define YYLIMIT l
+#define YYMARKER q
+#define YYFILL(n) { if (!fill(p, n, &l)) break; }
+
+ for(;;)
+ {
+/*!re2c
+ re2c:indent:top = 2;
+ "0"[0-9]+ { printf("Oct\n"); continue; }
+ [1-9][0-9]* { printf("Num\n"); continue; }
+ "0" { printf("Num\n"); continue; }
+ "+" { printf("+\n"); continue; }
+ "-" { printf("+\n"); continue; }
+ "\000" { printf("EOF\n"); return 0; }
+ [^] { printf("ERR\n"); return 1; }
+*/
+ }
+ printf("OOD\n"); return 2;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(argv[1]);
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_003.re b/tools/re2c/examples/001_upn_calculator/calc_003.re
new file mode 100644
index 000000000..e48aec928
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_003.re
@@ -0,0 +1,61 @@
+/* re2c lesson 001_upn_calculator, calc_003, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- making use of YYFILL
+
+ . Again provide the length of the input to generate the limit only once. Now
+ we can use YYFILL() to detect the end and simply return since YYFILL() is
+ only being used if the next scanner run might use more chars then YYLIMIT
+ allows.
+ . Note that we now use (s+l+2) instead of (s+l) as we did in lesson_001. In
+ the first lesson we did not quit from YYFILL() and used a special rule to
+ detect the end of input. Here we use the fact that we know the exact end
+ of input and that this length does not include the terminating zero. Since
+ YYLIMIT points to the first character behind the used buffer we use "+ 2".
+ If we would use "+1" we could drop the "\000" rule but could no longer
+ distinguish between end of input and out of data.
+
+*/
+
+#include
+#include
+#include
+
+int scan(char *s, int l)
+{
+ char *p = s;
+ char *q = 0;
+#define YYCTYPE char
+#define YYCURSOR p
+#define YYLIMIT (s+l+2)
+#define YYMARKER q
+#define YYFILL(n) { printf("OOD\n"); return 2; }
+
+ for(;;)
+ {
+/*!re2c
+ re2c:indent:top = 2;
+ "0"[0-9]+ { printf("Oct\n"); continue; }
+ [1-9][0-9]* { printf("Num\n"); continue; }
+ "0" { printf("Num\n"); continue; }
+ "+" { printf("+\n"); continue; }
+ "-" { printf("+\n"); continue; }
+ "\000" { printf("EOF\n"); return 0; }
+ [^] { printf("ERR\n"); return 1; }
+*/
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(argv[1], strlen(argv[1]));
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_004.re b/tools/re2c/examples/001_upn_calculator/calc_004.re
new file mode 100644
index 000000000..977e438bf
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_004.re
@@ -0,0 +1,78 @@
+/* re2c lesson 001_upn_calculator, calc_004, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- making use of definitions
+ . We provide complex rules as definitions. We can even have definitions made
+ up from other definitions. And we could also use definitions as part of
+ rules and not only as full rules as shown in this lesson.
+
+- showing the tokens
+ . re2c does not store the beginning of a token on its own but we can easily
+ do this by providing variable, in our case t, that is set to YYCURSOR on
+ every loop. If we were not using a loop here the token, we could have used
+ s instead of a new variable instead.
+ . As we use the token for an output function that requires a terminating zero
+ we copy the token. Alternatively we could store the end of the token, then
+ replace it with a zero character and replace it after the token has been
+ used. However that approach is not always acceptable.
+
+*/
+
+#include
+#include
+#include
+
+char * tokendup(const char *t, const char *l)
+{
+ size_t n = l -t + 1;
+ char *r = (char*)malloc(n);
+
+ memmove(r, t, n-1);
+ r[n] = '\0';
+ return r;
+}
+
+int scan(char *s, int l)
+{
+ char *p = s;
+ char *q = 0;
+ char *t;
+#define YYCTYPE char
+#define YYCURSOR p
+#define YYLIMIT (s+l+2)
+#define YYMARKER q
+#define YYFILL(n) { printf("OOD\n"); return 2; }
+
+ for(;;)
+ {
+ t = p;
+/*!re2c
+ re2c:indent:top = 2;
+
+ DIGIT = [0-9] ;
+ OCT = "0" DIGIT+ ;
+ INT = "0" | ( [1-9] DIGIT* ) ;
+
+ OCT { t = tokendup(t, p); printf("Oct: %s\n", t); free(t); continue; }
+ INT { t = tokendup(t, p); printf("Num: %s\n", t); free(t); continue; }
+ "+" { printf("+\n"); continue; }
+ "-" { printf("+\n"); continue; }
+ "\000" { printf("EOF\n"); return 0; }
+ [^] { printf("ERR\n"); return 1; }
+*/
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(argv[1], strlen(argv[1]));
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_005.re b/tools/re2c/examples/001_upn_calculator/calc_005.re
new file mode 100644
index 000000000..6ae2a484c
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_005.re
@@ -0,0 +1,144 @@
+/* re2c lesson 001_upn_calculator, calc_005, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- turning this lesson into an easy calculator
+ . We are going to write an UPN calculator so we need an additional rule to
+ ignore white space.
+ . Then we need to store the scanned input somewhere and do our math on it.
+ . Also we need to scan all arguments since the main c code gets the input
+ split up into chunks.
+ . In contrast to what we did before we now add a variable res that holds the
+ scanner state. We initialize that variable to 0 and quit the loop when it
+ is non zero. This will also be our return value so that we can use it in
+ function main to generate error information.
+ . To support operating systems where ' and " get passed in program arguments
+ we check for them being first and last input character. If so we correct
+ input pointer and input length. Since now our scanner might not see a
+ terminating zero we change YYLIMIT again and drop the special zero rule.
+*/
+
+#include
+#include
+#include
+
+#define DEBUG(stmt) stmt
+
+int stack[4];
+int depth = 0;
+
+int push_num(const char *t, const char *l, int radix)
+{
+ int num = 0;
+
+ if (depth >= sizeof(stack))
+ {
+ return 3;
+ }
+
+ --t;
+ while(++t < l)
+ {
+ num = num * radix + (*t - '0');
+ }
+ DEBUG(printf("Num: %d\n", num));
+
+ stack[depth++] = num;
+ return 0;
+}
+
+int stack_add()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] + stack[depth];
+ return 0;
+}
+
+int stack_sub()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] - stack[depth];
+ return 0;
+}
+
+int scan(char *s, int l)
+{
+ char *p = s;
+ char *q = 0;
+ char *t;
+ int res = 0;
+
+#define YYCTYPE char
+#define YYCURSOR p
+#define YYLIMIT (s+l+1)
+#define YYMARKER q
+#define YYFILL(n) { return depth == 1 ? 0 : 2; }
+
+ while(!res)
+ {
+ t = p;
+/*!re2c
+ re2c:indent:top = 2;
+
+ DIGIT = [0-9] ;
+ OCT = "0" DIGIT+ ;
+ INT = "0" | ( [1-9] DIGIT* ) ;
+ WS = [ \t]+ ;
+
+ WS { continue; }
+ OCT { res = push_num(t, p, 8); continue; }
+ INT { res = push_num(t, p, 10); continue; }
+ "+" { res = stack_add(); continue; }
+ "-" { res = stack_sub(); continue; }
+ [^] { res = 1; continue; }
+*/
+ }
+ return res;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ char *inp;
+ int res = 0, argp = 0, len;
+
+ while(!res && ++argp < argc)
+ {
+ inp = argv[argp];
+ len = strlen(inp);
+ if (inp[0] == '\"' && inp[len-1] == '\"')
+ {
+ ++inp;
+ len -=2;
+ }
+ res = scan(inp, len);
+ }
+ switch(res)
+ {
+ case 0:
+ printf("Result: %d\n", stack[0]);
+ return 0;
+ case 1:
+ fprintf(stderr, "Illegal character in input.\n");
+ return 1;
+ case 2:
+ fprintf(stderr, "Premature end of input.\n");
+ return 2;
+ case 3:
+ fprintf(stderr, "Stack overflow.\n");
+ return 3;
+ case 4:
+ fprintf(stderr, "Stack underflow.\n");
+ return 4;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_006.s.re b/tools/re2c/examples/001_upn_calculator/calc_006.s.re
new file mode 100644
index 000000000..10da31cd1
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_006.s.re
@@ -0,0 +1,162 @@
+/* re2c lesson 001_upn_calculator, calc_006, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- avoiding YYFILL()
+ . We use the inplace configuration re2c:yyfill to suppress generation of
+ YYFILL() blocks. This of course means we no longer have to provide the
+ macro.
+ . We also drop the YYMARKER stuff since we know that re2c does not generate
+ it for this example.
+ . Since re2c does no longer check for out of data situations we must do this.
+ For that reason we first reintroduce our zero rule and second we need to
+ ensure that the scanner does not take more than one bytes in one go.
+
+ In the example suppose "0" is passed. The scanner reads the first "0" and
+ then is in an undecided state. The scanner can earliest decide on the next
+ char what the token is. In case of a zero the input ends and it was a
+ number, 0 to be precise. In case of a digit it is an octal number and the
+ next character needs to be read. In case of any other character the scanner
+ will detect an error with the any rule [^].
+
+ Now the above shows that the scanner may read two characters directly. But
+ only if the first is a "0". So we could easily check that if the first char
+ is "0" and the next char is a digit then yet another charcter is present.
+ But we require our inut to be zero terminated. And that means we do not
+ have to check anything for this scanner.
+
+ However with other rule sets re2c might read more then one character in a
+ row. In those cases it is normally hard to impossible to avoid YYFILL.
+
+- optimizing the generated code by using -s command line switch of re2c
+ . This tells re2c to generate code that uses if statements rather
+ then endless switch/case expressions where appropriate. Note that the
+ generated code now requires the input to be unsigned char rather than char
+ due to the way comparisons are generated.
+*/
+
+#include
+#include
+#include
+
+#define DEBUG(stmt) stmt
+
+int stack[4];
+int depth = 0;
+
+int push_num(const unsigned char *t, const unsigned char *l, int radix)
+{
+ int num = 0;
+
+ if (depth >= sizeof(stack))
+ {
+ return 3;
+ }
+
+ --t;
+ while(++t < l)
+ {
+ num = num * radix + (*t - (unsigned char)'0');
+ }
+ DEBUG(printf("Num: %d\n", num));
+
+ stack[depth++] = num;
+ return 0;
+}
+
+int stack_add()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] + stack[depth];
+ DEBUG(printf("+\n"));
+ return 0;
+}
+
+int stack_sub()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] - stack[depth];
+ DEBUG(printf("-\n"));
+ return 0;
+}
+
+int scan(char *s)
+{
+ unsigned char *p = (unsigned char*)s;
+ unsigned char *t;
+ int res = 0;
+
+#define YYCTYPE unsigned char
+#define YYCURSOR p
+
+ while(!res)
+ {
+ t = p;
+/*!re2c
+ re2c:indent:top = 2;
+ re2c:yyfill:enable = 0;
+
+ DIGIT = [0-9] ;
+ OCT = "0" DIGIT+ ;
+ INT = "0" | ( [1-9] DIGIT* ) ;
+ WS = [ \t]+ ;
+
+ WS { continue; }
+ OCT { res = push_num(t, p, 8); continue; }
+ INT { res = push_num(t, p, 10); continue; }
+ "+" { res = stack_add(); continue; }
+ "-" { res = stack_sub(); continue; }
+ "\000" { res = depth == 1 ? 0 : 2; break; }
+ [^] { res = 1; continue; }
+*/
+ }
+ return res;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ char *inp;
+ int res = 0, argp = 0, len;
+
+ while(!res && ++argp < argc)
+ {
+ inp = strdup(argv[argp]);
+ len = strlen(inp);
+ if (inp[0] == '\"' && inp[len-1] == '\"')
+ {
+ inp[len - 1] = '\0';
+ ++inp;
+ }
+ res = scan(inp);
+ free(inp);
+ }
+ switch(res)
+ {
+ case 0:
+ printf("Result: %d\n", stack[0]);
+ return 0;
+ case 1:
+ fprintf(stderr, "Illegal character in input.\n");
+ return 1;
+ case 2:
+ fprintf(stderr, "Premature end of input.\n");
+ return 2;
+ case 3:
+ fprintf(stderr, "Stack overflow.\n");
+ return 3;
+ case 4:
+ fprintf(stderr, "Stack underflow.\n");
+ return 4;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_007.b.re b/tools/re2c/examples/001_upn_calculator/calc_007.b.re
new file mode 100644
index 000000000..523819654
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_007.b.re
@@ -0,0 +1,135 @@
+/* re2c lesson 001_upn_calculator, calc_007, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- optimizing the generated code by using -b command line switch of re2c
+ . This tells re2c to generate code that uses a decision table. The -b switch
+ also contains the -s behavior. And -b also requires the input to be
+ unsigned chars.
+*/
+
+#include
+#include
+#include
+
+#define DEBUG(stmt) stmt
+
+int stack[4];
+int depth = 0;
+
+int push_num(const unsigned char *t, const unsigned char *l, int radix)
+{
+ int num = 0;
+
+ if (depth >= sizeof(stack))
+ {
+ return 3;
+ }
+
+ --t;
+ while(++t < l)
+ {
+ num = num * radix + (*t - (unsigned char)'0');
+ }
+ DEBUG(printf("Num: %d\n", num));
+
+ stack[depth++] = num;
+ return 0;
+}
+
+int stack_add()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] + stack[depth];
+ DEBUG(printf("+\n"));
+ return 0;
+}
+
+int stack_sub()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] - stack[depth];
+ DEBUG(printf("+\n"));
+ return 0;
+}
+
+int scan(char *s)
+{
+ unsigned char *p = (unsigned char*)s;
+ unsigned char *t;
+ int res = 0;
+
+#define YYCTYPE unsigned char
+#define YYCURSOR p
+
+ while(!res)
+ {
+ t = p;
+/*!re2c
+ re2c:indent:top = 2;
+ re2c:yyfill:enable = 0;
+
+ DIGIT = [0-9] ;
+ OCT = "0" DIGIT+ ;
+ INT = "0" | ( [1-9] DIGIT* ) ;
+ WS = [ \t]+ ;
+
+ WS { continue; }
+ OCT { res = push_num(t, p, 8); continue; }
+ INT { res = push_num(t, p, 10); continue; }
+ "+" { res = stack_add(); continue; }
+ "-" { res = stack_sub(); continue; }
+ "\000" { res = depth == 1 ? 0 : 2; break; }
+ [^] { res = 1; continue; }
+*/
+ }
+ return res;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ char *inp;
+ int res = 0, argp = 0, len;
+
+ while(!res && ++argp < argc)
+ {
+ inp = strdup(argv[argp]);
+ len = strlen(inp);
+ if (inp[0] == '\"' && inp[len-1] == '\"')
+ {
+ inp[len - 1] = '\0';
+ ++inp;
+ }
+ res = scan(inp);
+ free(inp);
+ }
+ switch(res)
+ {
+ case 0:
+ printf("Result: %d\n", stack[0]);
+ return 0;
+ case 1:
+ fprintf(stderr, "Illegal character in input.\n");
+ return 1;
+ case 2:
+ fprintf(stderr, "Premature end of input.\n");
+ return 2;
+ case 3:
+ fprintf(stderr, "Stack overflow.\n");
+ return 3;
+ case 4:
+ fprintf(stderr, "Stack underflow.\n");
+ return 4;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/calc_008.b.re b/tools/re2c/examples/001_upn_calculator/calc_008.b.re
new file mode 100644
index 000000000..ed1a088e4
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/calc_008.b.re
@@ -0,0 +1,158 @@
+/* re2c lesson 001_upn_calculator, calc_008, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- using -b with signed character input
+ . Since the code is being generated with -b switch re2c requires the internal
+ character variable yych to use an unsigned character type. For that reason
+ the previous lessons had a conversion at the beginning of their scan()
+ function. Other re2c generated code often have the scanners work completely
+ on unsigned input. Thus requesting a conversion.
+
+ To avoid the conversion on input, re2c allows to do the conversion when
+ reading the internal yych variable. To enable that conversion you need to
+ use the implace configuration 're2c:yych:conversion' and set it to 1. This
+ will change the generated code to insert conversions to YYCTYPE whenever
+ yych is being read.
+
+- More inplace configurations for better/nicer code
+ . re2c allows to overwrite the generation of any define, label or variable
+ used in the generated code. For example we overwrite the 'yych' variable
+ name to 'curr' using inplace configuration 're2c:variable:yych = curr;'.
+
+ . We further more use inplace configurations instead of defines. This allows
+ to use correct conversions to 'unsigned char' instead of having to convert
+ to 'YYCTYPE' when placing 're2c:define:YYCTYPE = "unsigned char";' infront
+ of 're2c:yych:conversion'. Note that we have to use apostrophies for the
+ first setting as it contains a space.
+
+ . Last but not least we use 're2c:labelprefix = scan' to change the prefix
+ of generated labels.
+*/
+
+#include
+#include
+#include
+
+#define DEBUG(stmt) stmt
+
+int stack[4];
+int depth = 0;
+
+int push_num(const char *t, const char *l, int radix)
+{
+ int num = 0;
+
+ if (depth >= sizeof(stack))
+ {
+ return 3;
+ }
+
+ --t;
+ while(++t < l)
+ {
+ num = num * radix + (*t - '0');
+ }
+ DEBUG(printf("Num: %d\n", num));
+
+ stack[depth++] = num;
+ return 0;
+}
+
+int stack_add()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] + stack[depth];
+ DEBUG(printf("+\n"));
+ return 0;
+}
+
+int stack_sub()
+{
+ if (depth < 2) return 4;
+
+ --depth;
+ stack[depth-1] = stack[depth-1] - stack[depth];
+ DEBUG(printf("+\n"));
+ return 0;
+}
+
+int scan(char *p)
+{
+ char *t;
+ int res = 0;
+
+ while(!res)
+ {
+ t = p;
+/*!re2c
+ re2c:define:YYCTYPE = "unsigned char";
+ re2c:define:YYCURSOR = p;
+ re2c:variable:yych = curr;
+ re2c:indent:top = 2;
+ re2c:yyfill:enable = 0;
+ re2c:yych:conversion = 1;
+ re2c:labelprefix = scan;
+
+ DIGIT = [0-9] ;
+ OCT = "0" DIGIT+ ;
+ INT = "0" | ( [1-9] DIGIT* ) ;
+ WS = [ \t]+ ;
+
+ WS { continue; }
+ OCT { res = push_num(t, p, 8); continue; }
+ INT { res = push_num(t, p, 10); continue; }
+ "+" { res = stack_add(); continue; }
+ "-" { res = stack_sub(); continue; }
+ "\000" { res = depth == 1 ? 0 : 2; break; }
+ [^] { res = 1; continue; }
+*/
+ }
+ return res;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ char *inp;
+ int res = 0, argp = 0, len;
+
+ while(!res && ++argp < argc)
+ {
+ inp = strdup(argv[argp]);
+ len = strlen(inp);
+ if (inp[0] == '\"' && inp[len-1] == '\"')
+ {
+ inp[len - 1] = '\0';
+ ++inp;
+ }
+ res = scan(inp);
+ free(inp);
+ }
+ switch(res)
+ {
+ case 0:
+ printf("Result: %d\n", stack[0]);
+ return 0;
+ case 1:
+ fprintf(stderr, "Illegal character in input.\n");
+ return 1;
+ case 2:
+ fprintf(stderr, "Premature end of input.\n");
+ return 2;
+ case 3:
+ fprintf(stderr, "Stack overflow.\n");
+ return 3;
+ case 4:
+ fprintf(stderr, "Stack underflow.\n");
+ return 4;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 0;
+ }
+}
diff --git a/tools/re2c/examples/001_upn_calculator/windows/HiResTimer.h b/tools/re2c/examples/001_upn_calculator/windows/HiResTimer.h
new file mode 100644
index 000000000..585a1d98f
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/windows/HiResTimer.h
@@ -0,0 +1,54 @@
+/**
+ * @file HiResTimer.h
+ * @brief
+ * @note
+ */
+
+#ifndef _HI_RES_TIMER_H_
+#define _HI_RES_TIMER_H_
+
+#ifdef WIN32
+#include // probably already done in stdafx.h
+static LARGE_INTEGER start;
+static LARGE_INTEGER stop;
+static LARGE_INTEGER freq;
+static _int64 elapsedCounts;
+static double elapsedMillis;
+static double elapsedMicros;
+static HANDLE processHandle;
+static DWORD prevPriorityClass;
+
+void HrtInit()
+{
+ processHandle = GetCurrentProcess();
+ prevPriorityClass = GetPriorityClass(processHandle);
+ QueryPerformanceFrequency(&freq);
+}
+
+void HrtStart()
+{
+ QueryPerformanceCounter(&start);
+}
+
+void HrtSetPriority(DWORD priority)
+{
+ int flag;
+ prevPriorityClass = GetPriorityClass(processHandle);
+ flag = SetPriorityClass(processHandle, priority);
+}
+
+void HrtResetPriority(void)
+{
+ int flag = SetPriorityClass(processHandle, prevPriorityClass);
+}
+
+double HrtElapsedMillis()
+{
+ QueryPerformanceCounter(&stop);
+ elapsedCounts = (stop.QuadPart - start.QuadPart);
+ elapsedMillis = ((elapsedCounts * 1000.0) / freq.QuadPart);
+ return elapsedMillis;
+}
+
+#endif
+#endif
\ No newline at end of file
diff --git a/tools/re2c/examples/001_upn_calculator/windows/main.b.re b/tools/re2c/examples/001_upn_calculator/windows/main.b.re
new file mode 100644
index 000000000..1600b83d2
--- /dev/null
+++ b/tools/re2c/examples/001_upn_calculator/windows/main.b.re
@@ -0,0 +1,291 @@
+/* re2c lesson 001_upn_calculator, main.b.re, (c) M. Boerger, L. Allan 2006 */
+/*!ignore:re2c
+
+- basic interface for string reading
+
+ . We define the macros YYCTYPE, YYCURSOR, YYLIMIT, YYMARKER, YYFILL
+ . YYCTYPE is the type re2c operates on or in other words the type that
+ it generates code for. While it is not a big difference when we were
+ using 'unsigned char' here we would need to run re2c with option -w
+ to fully support types with sieof() > 1.
+ . YYCURSOR is used internally and holds the current scanner position. In
+ expression handlers, the code blocks after re2c expressions, this can be
+ used to identify the end of the token.
+ . YYMARKER is not always being used so we set an initial value to avoid
+ a compiler warning.
+ . YYLIMIT stores the end of the input. Unfortunatley we have to use strlen()
+ in this lesson. In the next example we see one way to get rid of it.
+ . We use a 'for(;;)'-loop around the scanner block. We could have used a
+ 'while(1)'-loop instead but some compilers generate a warning for it.
+ . To make the output more readable we use 're2c:indent:top' scanner
+ configuration that configures re2c to prepend a single tab (the default)
+ to the beginning of each output line.
+ . The following lines are expressions and for each expression we output the
+ token name and continue the scanner loop.
+ . The second last token detects the end of our input, the terminating zero in
+ our input string. In other scanners detecting the end of input may vary.
+ For example binary code may contain \0 as valid input.
+ . The last expression accepts any input character. It tells re2c to accept
+ the opposit of the empty range. This includes numbers and our tokens but
+ as re2c goes from top to botton when evaluating the expressions this is no
+ problem.
+ . The first three rules show that re2c actually prioritizes the expressions
+ from top to bottom. Octal number require a starting "0" and the actual
+ number. Normal numbers start with a digit greater 0. And zero is finally a
+ special case. A single "0" is detected by the last rule of this set. And
+ valid ocal number is already being detected by the first rule. This even
+ includes multi "0" sequences that in octal notation also means zero.
+ Another way would be to only use two rules:
+ "0" [0-9]+
+ "0" | ( [1-9] [0-9]* )
+ A full description of re2c rule syntax can be found in the manual.
+*/
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#if _MSC_VER > 1200
+#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
+#endif // Prevents warning from vc7.1 complaining about redefinition
+
+#include
+#include
+#include
+#include
+#include
+#include "HiResTimer.h"
+
+static char gTestBuf[1000] = "";
+
+/**
+ * @brief Setup HiResolution timer and confirm it is working ok
+ */
+void InitHiResTimerAndVerifyWorking(void)
+{
+ double elapsed;
+ HrtInit();
+ HrtSetPriority(ABOVE_NORMAL_PRIORITY_CLASS);
+ HrtStart();
+ Sleep(100);
+ elapsed = HrtElapsedMillis();
+ if ((elapsed < 90) || (elapsed > 110)) {
+ printf("HiResTimer misbehaving: %f\n", elapsed);
+ exit(2);
+ }
+}
+
+/**
+ * @brief Scan for numbers in different formats
+ */
+int ScanFullSpeed(char *pzStrToScan, size_t lenStrToScan)
+{
+ unsigned char *pzCurScanPos = (unsigned char*)pzStrToScan;
+ unsigned char *pzBacktrackInfo = 0;
+#define YYCTYPE unsigned char
+#define YYCURSOR pzCurScanPos
+#define YYLIMIT (pzStrToScan+lenStrToScan)
+#define YYMARKER pzBacktrackInfo
+#define YYFILL(n)
+
+ for(;;)
+ {
+/*!re2c
+ re2c:indent:top = 2;
+ [1-9][0-9]* { continue; }
+ [0][0-9]+ { continue; }
+ "+" { continue; }
+ "-" { continue; }
+ "\000" { return 0; }
+ [^] { return 1; }
+*/
+ }
+}
+
+/**
+ * @brief Scan for numbers in different formats
+ */
+int scan(char *pzStrToScan, size_t lenStrToScan)
+{
+ unsigned char *pzCurScanPos = (unsigned char*)pzStrToScan;
+ unsigned char *pzBacktrackInfo = 0;
+#define YYCTYPE unsigned char
+#define YYCURSOR pzCurScanPos
+#define YYLIMIT (pzStrToScan+lenStrToScan)
+#define YYMARKER pzBacktrackInfo
+#define YYFILL(n)
+
+ for(;;)
+ {
+/*!re2c
+ re2c:indent:top = 2;
+ [1-9][0-9]* { printf("Num\n"); strcat(gTestBuf, "Num "); continue; }
+ [0][0-9]+ { printf("Oct\n"); strcat(gTestBuf, "Oct "); continue; }
+ "+" { printf("+\n"); strcat(gTestBuf, "+ "); continue; }
+ "-" { printf("-\n"); strcat(gTestBuf, "- "); continue; }
+ "\000" { printf("EOF\n"); return 0; }
+ [^] { printf("ERR\n"); strcat(gTestBuf, "ERR "); return 1; }
+*/
+ }
+}
+
+/**
+ * @brief Show high resolution elapsed time for 10,000 and 100,000 loops
+ */
+void DoTimingsOfStrnCmp(void)
+{
+ char testStr[] = "Hello, world";
+ int totLoops = 10000;
+ int totFoundCount = 0;
+ int foundCount = 0;
+ int loop;
+ int rc;
+ const int progressAnd = 0xFFFFF000;
+ double elapsed;
+
+ printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
+
+ HrtStart();
+ for (loop = 0; loop < totLoops; ++loop) {
+ foundCount = 0;
+ rc = strncmp(testStr, "Hello", 5);
+ if (rc == 0) {
+ foundCount++;
+ totFoundCount++;
+ if ((totFoundCount & progressAnd) == totFoundCount) {
+ printf("*");
+ }
+ }
+ }
+ elapsed = HrtElapsedMillis();
+ printf("\nstrncmp Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
+ printf("FoundCount each loop: %d\n", foundCount);
+ printf("TotalFoundCount for all loops: %d\n", totFoundCount);
+
+ totLoops = 100000;
+ HrtStart();
+ for (loop = 0; loop < totLoops; ++loop) {
+ foundCount = 0;
+ rc = strncmp(testStr, "Hello", 5);
+ if (rc == 0) {
+ foundCount++;
+ totFoundCount++;
+ if ((totFoundCount & progressAnd) == totFoundCount) {
+ printf("*");
+ }
+ }
+ }
+ elapsed = HrtElapsedMillis();
+ printf("\nstrncmp Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
+ printf("FoundCount each loop: %d\n", foundCount);
+ printf("TotalFoundCount for all loops: %d\n", totFoundCount);
+}
+
+/**
+ * @brief Show high resolution elapsed time for 10,000 and 100,000 loops
+ */
+void DoTimingsOfRe2c(void)
+{
+ char* testStrings[] = { "123", "1234", "+123", "01234", "-04321", "abc", "123abc" };
+ const int testCount = sizeof(testStrings) / sizeof(testStrings[0]);
+ int i;
+ int totLoops = 10000 / testCount; // Doing more than one per loop
+ int totFoundCount = 0;
+ int foundCount = 0;
+ int loop;
+ int rc;
+ const int progressAnd = 0xFFFFF000;
+ double elapsed;
+
+ printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
+
+ HrtStart();
+ for (loop = 0; loop < totLoops; ++loop) {
+ foundCount = 0;
+ strcpy(gTestBuf, "");
+ for (i = 0; i < testCount; ++i) {
+ char* pzCurStr = testStrings[i];
+ size_t len = strlen(pzCurStr); // Calc of strlen slows things down ... std::string?
+ rc = ScanFullSpeed(pzCurStr, len);
+ if (rc == 0) {
+ foundCount++;
+ totFoundCount++;
+ if ((totFoundCount & progressAnd) == totFoundCount) {
+ printf("*");
+ }
+ }
+ }
+ }
+ elapsed = HrtElapsedMillis();
+ printf("\nRe2c Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
+ printf("FoundCount each loop: %d\n", foundCount);
+ printf("TotalFoundCount for all loops: %d\n", totFoundCount);
+
+ totLoops = 100000 / testCount;
+ printf("\n\n%d loops with * every %d loops to confirm\n", totLoops, ((~progressAnd) + 1));
+
+ HrtStart();
+ for (loop = 0; loop < totLoops; ++loop) {
+ foundCount = 0;
+ strcpy(gTestBuf, "");
+ for (i = 0; i < testCount; ++i) {
+ char* pzCurStr = testStrings[i];
+ size_t len = strlen(pzCurStr); // Calc of strlen slows things down ... std::string?
+ rc = ScanFullSpeed(pzCurStr, len);
+ if (rc == 0) {
+ foundCount++;
+ totFoundCount++;
+ if ((totFoundCount & progressAnd) == totFoundCount) {
+ printf("*");
+ }
+ }
+ }
+ }
+ elapsed = HrtElapsedMillis();
+ printf("\nRe2c Elapsed for %7d loops milliseconds: %7.3f\n", totLoops, elapsed);
+ printf("FoundCount each loop: %d\n", foundCount);
+ printf("TotalFoundCount for all loops: %d\n", totFoundCount);
+}
+
+/**
+ * @brief Entry point for console app
+ */
+int main(int argc, char **argv)
+{
+ char testStr_A[] = "123";
+ char* testStr_B = "456";
+ char* testStrings[] = { "123", "1234", "+123", "01234", "-04321", "abc", "123abc" };
+ const int testCount = sizeof(testStrings) / sizeof(testStrings[0]);
+ int i;
+
+ int rc = scan(testStr_A, 3);
+ printf("rc: %d\n", rc);
+
+ rc = scan(testStr_B, 3);
+ printf("rc: %d\n", rc);
+
+ rc = scan("789", 3);
+ printf("rc: %d\n", rc);
+
+ strcpy(gTestBuf, "");
+ for (i = 0; i < testCount; ++i) {
+ char* pzCurStr = testStrings[i];
+ size_t len = strlen(pzCurStr);
+ scan(pzCurStr, len);
+ }
+ printf("%s\n", gTestBuf);
+ rc = strcmp(gTestBuf, "Num Num + Num Oct - Oct ERR Num ERR ");
+ if (rc == 0) {
+ printf("Success\n");
+ }
+ else {
+ printf("Failure\n");
+ }
+ assert(0 == rc); // Doesn't work with Release build
+
+ InitHiResTimerAndVerifyWorking();
+
+ DoTimingsOfStrnCmp();
+
+ DoTimingsOfRe2c();
+
+ return 0;
+}
diff --git a/tools/re2c/examples/002_strip_comments/README b/tools/re2c/examples/002_strip_comments/README
new file mode 100644
index 000000000..353d66904
--- /dev/null
+++ b/tools/re2c/examples/002_strip_comments/README
@@ -0,0 +1,21 @@
+re2c lesson 002_strip_comments, (c) M. Boerger 2006
+
+In this lesson you will learn how to use multiple scanner blocks and how to
+read the input from a file instead of a zero terminated string. In the end you
+will have a scanner that filters comments out of c source files but keeps re2c
+comments.
+
+The first scanner can be generated with:
+
+ re2c -s -o t.c strip_001.s.re
+
+In the second step we will learn about YYMARKER that stores backtracking
+information.
+
+ re2c -s -0 t.c strip_002.b.re
+
+The third step brings trailing contexts that are stored in YYCTXMARKER. We also
+change to use -b instead of -s option since the scanner gets more and more
+complex.
+
+ re2c -b -0 t.c strip_002.b.re
diff --git a/tools/re2c/examples/002_strip_comments/strip_001.s.re b/tools/re2c/examples/002_strip_comments/strip_001.s.re
new file mode 100644
index 000000000..5525ae3c9
--- /dev/null
+++ b/tools/re2c/examples/002_strip_comments/strip_001.s.re
@@ -0,0 +1,147 @@
+/* re2c lesson 002_strip_comments, strip_001.s, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- basic interface for file reading
+ . This scanner will read chunks of input from a file. The easiest way would
+ be to read the whole file into a memory buffer and use that a zero
+ terminated string.
+ . Instead we want to read input chunks of a reasonable size as they are neede
+ by the scanner. Thus we basically need YYFILL(n) to call fread(n).
+ . Before we provide a buffer that we constantly reallocate we instead use
+ one buffer that we get from the stack or global memory just once. When we
+ reach the end of the buffer we simply move the beginning of our input
+ that is somewhere in our buffer to the beginning of our buffer and then
+ append the next chunk of input to the correct end inside our buffer.
+ . As re2c scanners might read more than one character we need to ensure our
+ buffer is long enough. We can use re2c to inform about the maximum size
+ by placing a "!max:re2c" comment somewhere. This gets translated to a
+ "#define YYMAXFILL " line where is the maximum length value. This
+ define can be used as precompiler condition.
+
+- multiple scanner blocks
+ . We use a main scanner block that outputs every input character unless the
+ input is two /s or a / followed by a *. In the latter two cases we switch
+ to a special c++ comment and a comment block respectively.
+ . Both special blocks simply detect their end ignore any other character.
+ . The c++ block is a bit special. Since the terminating new line needs to
+ be output and that can either be a new line or a carridge return followed
+ by a new line.
+ . In order to ensure that we do not read behind our buffer we reset the token
+ pointer to the cursor on every scanner run.
+*/
+
+#include
+#include
+#include
+
+/*!max:re2c */
+#define BSIZE 128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define YYCTYPE unsigned char
+#define YYCURSOR s.cur
+#define YYLIMIT s.lim
+#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
+
+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;
+}
+
+int scan(FILE *fp)
+{
+ int res = 0;
+ Scanner s;
+
+ if (!fp)
+ {
+ return 1; /* no file was opened */
+ }
+
+ s.fp = fp;
+
+ fill(&s, 0);
+
+ for(;;)
+ {
+ s.tok = s.cur;
+/*!re2c
+ re2c:indent:top = 2;
+
+ NL = "\r"? "\n" ;
+ ANY = [^] ;
+
+ "/" "/" { goto cppcomment; }
+ "/" "*" { goto comment; }
+ ANY { fputc(*s.tok, stdout); continue; }
+*/
+comment:
+ s.tok = s.cur;
+/*!re2c
+ "*" "/" { continue; }
+ ANY { goto comment; }
+*/
+cppcomment:
+ s.tok = s.cur;
+/*!re2c
+ NL { fwrite(s.tok, 1, s.cur - s.tok, stdout); continue; }
+ ANY { goto cppcomment; }
+*/
+ }
+
+ if (fp != stdin)
+ {
+ fclose(fp); /* close only if not stdin */
+ }
+ return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 1;
+ }
+}
diff --git a/tools/re2c/examples/002_strip_comments/strip_002.s.re b/tools/re2c/examples/002_strip_comments/strip_002.s.re
new file mode 100644
index 000000000..3c2a6cf8c
--- /dev/null
+++ b/tools/re2c/examples/002_strip_comments/strip_002.s.re
@@ -0,0 +1,162 @@
+/* re2c lesson 002_strip_comments, strip_002.s, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- complexity
+ . When a comment is preceeded by a new line and followed by whitespace and a
+ new line then we can drop the trailing whitespace and new line.
+ . Additional to what we strip out already what about two consequtive comment
+ blocks? When two comments are only separated by whitespace we want to drop
+ both. In other words when detecting the end of a comment block we need to
+ check whether it is followed by only whitespace and the a new comment in
+ which case we continure ignoring the input. If it is followed only by white
+ space and a new line we strip out the new white space and new line. In any
+ other case we start outputting all that follows.
+ But we cannot simply use the following two rules:
+ "*" "/" WS* "/" "*" { continue; }
+ "*" "/" WS* NL { continue; }
+ The main problem is that WS* can get bigger then our buffer, so we need a
+ new scanner.
+ . Meanwhile our scanner gets a bit more complex and we have to add two more
+ things. First the scanner code now uses a YYMARKER to store backtracking
+ information.
+
+- backtracking information
+ . When the scanner has two rules that can have the same beginning but a
+ different ending then it needs to store the position that identifies the
+ common part. This is called backtracking. As mentioned above re2c expects
+ you to provide compiler define YYMARKER and a pointer variable.
+ . When shifting buffer contents as done in our fill function the marker needs
+ to be corrected, too.
+
+*/
+
+#include
+#include
+#include
+
+/*!max:re2c */
+#define BSIZE 128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define YYCTYPE unsigned char
+#define YYCURSOR s.cur
+#define YYLIMIT s.lim
+#define YYMARKER s.mrk
+#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+ FILE *fp;
+ unsigned char *cur, *tok, *lim, *eof, *mrk;
+ unsigned char buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+ if (!len)
+ {
+ s->cur = s->tok = s->lim = s->mrk = 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;
+ s->mrk -= 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;
+}
+
+void echo(Scanner *s)
+{
+ fwrite(s->tok, 1, s->cur - s->tok, stdout);
+}
+
+int scan(FILE *fp)
+{
+ int res = 0;
+ Scanner s;
+
+ if (!fp)
+ {
+ return 1; /* no file was opened */
+ }
+
+ s.fp = fp;
+
+ fill(&s, 0);
+
+ for(;;)
+ {
+ s.tok = s.cur;
+/*!re2c
+ re2c:indent:top = 2;
+
+ NL = "\r"? "\n" ;
+ WS = [\r\n\t ] ;
+ ANY = [^] ;
+
+ "/" "/" { goto cppcomment; }
+ "/" "*" { goto comment; }
+ ANY { fputc(*s.tok, stdout); continue; }
+*/
+comment:
+ s.tok = s.cur;
+/*!re2c
+ "*" "/" { goto commentws; }
+ ANY { goto comment; }
+*/
+commentws:
+ s.tok = s.cur;
+/*!re2c
+ NL { echo(&s); continue; }
+ WS { goto commentws; }
+ ANY { echo(&s); continue; }
+*/
+cppcomment:
+ s.tok = s.cur;
+/*!re2c
+ NL { echo(&s); continue; }
+ ANY { goto cppcomment; }
+*/
+ }
+
+ if (fp != stdin)
+ {
+ fclose(fp); /* close only if not stdin */
+ }
+ return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 1;
+ }
+}
diff --git a/tools/re2c/examples/002_strip_comments/strip_003.b.re b/tools/re2c/examples/002_strip_comments/strip_003.b.re
new file mode 100644
index 000000000..a7b1a5c72
--- /dev/null
+++ b/tools/re2c/examples/002_strip_comments/strip_003.b.re
@@ -0,0 +1,179 @@
+/* re2c lesson 002_strip_comments, strip_003.b, (c) M. Boerger 2006 - 2007 */
+/*!ignore:re2c
+
+- more complexity
+ . Right now we strip out trailing white space and new lines after a comment
+ block. This can be a problem when the comment block was not preceeded by
+ a new line.
+ . The solution is to use trailing contexts.
+
+- trailing contexts
+ . Re2c allows to check for a portion of input and only recognize it when it
+ is followed by another portion. This is called a trailing context.
+ . The trailing context is not part of the identified input. That means that
+ it follows exactly at the cursor. A consequence is that the scanner has
+ already read more input and on the next run you need to restore begining
+ of input, in our case s.tok, from the cursor, here s.cur, rather then
+ restoring to the beginning of the buffer. This way the scanner can reuse
+ the portion it has already read.
+ . The position of the trailing context is stored in YYCTXMARKER for which
+ a pointer variable needs to be provided.
+ . As with YYMARKER the corrsponding variable needs to be corrected if we
+ shift in some buffer.
+ . Still this is not all we need to solve the problem. What is left is that
+ the information whether we detected a trailing context was detected has to
+ be stored somewhere. This is done by the new variable nlcomment.
+
+- formatting
+ . Until now we only used single line expression code and we always had the
+ opening { on the same line as the rule itself. If we have multiline rule
+ code and care for formatting we can no longer rely on re2c. Now we have
+ to indent the rule code ourself. Also we need to take care of the opening
+ {. If we keep it on the same line as the rule then re2c will indent it
+ correctly and the emitted #line informations will be correct. If we place
+ it on the next line then the #line directive will also point to that line
+ and not to the rule.
+*/
+
+#include
+#include
+#include
+
+/*!max:re2c */
+#define BSIZE 128
+
+#if BSIZE < YYMAXFILL
+# error BSIZE must be greater YYMAXFILL
+#endif
+
+#define YYCTYPE unsigned char
+#define YYCURSOR s.cur
+#define YYLIMIT s.lim
+#define YYMARKER s.mrk
+#define YYCTXMARKER s.ctx
+#define YYFILL(n) { if ((res = fill(&s, n)) >= 0) break; }
+
+typedef struct Scanner
+{
+ FILE *fp;
+ unsigned char *cur, *tok, *lim, *eof, *ctx, *mrk;
+ unsigned char buffer[BSIZE];
+} Scanner;
+
+int fill(Scanner *s, int len)
+{
+ if (!len)
+ {
+ s->cur = s->tok = s->lim = s->mrk = 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;
+ s->mrk -= cnt;
+ s->ctx -= 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;
+}
+
+void echo(Scanner *s)
+{
+ fwrite(s->tok, 1, s->cur - s->tok, stdout);
+}
+
+int scan(FILE *fp)
+{
+ int res = 0;
+ int nlcomment = 0;
+ Scanner s;
+
+ if (!fp)
+ {
+ return 1; /* no file was opened */
+ }
+
+ s.fp = fp;
+
+ fill(&s, 0);
+
+ for(;;)
+ {
+ s.tok = s.cur;
+/*!re2c
+ re2c:indent:top = 2;
+
+ NL = "\r"? "\n" ;
+ WS = [\r\n\t ] ;
+ ANY = [^] ;
+
+ "/" "/" { goto cppcomment; }
+ NL / "/""*" { echo(&s); nlcomment = 1; continue; }
+ "/" "*" { goto comment; }
+ ANY { fputc(*s.tok, stdout); continue; }
+*/
+comment:
+ s.tok = s.cur;
+/*!re2c
+ "*" "/" { goto commentws; }
+ ANY { goto comment; }
+*/
+commentws:
+ s.tok = s.cur;
+/*!re2c
+ NL? "/" "*" { goto comment; }
+ NL {
+ if (!nlcomment)
+ {
+ echo(&s);
+ }
+ nlcomment = 0;
+ continue;
+ }
+ WS { goto commentws; }
+ ANY { echo(&s); nlcomment = 0; continue; }
+*/
+cppcomment:
+ s.tok = s.cur;
+/*!re2c
+ NL { echo(&s); continue; }
+ ANY { goto cppcomment; }
+*/
+ }
+
+ if (fp != stdin)
+ {
+ fclose(fp); /* close only if not stdin */
+ }
+ return res; /* return result */
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ {
+ return scan(!strcmp(argv[1], "-") ? stdin : fopen(argv[1], "r"));
+ }
+ else
+ {
+ fprintf(stderr, "%s \n", argv[0]);
+ return 1;
+ }
+}
diff --git a/tools/re2c/examples/input_custom/fixed.re b/tools/re2c/examples/input_custom/fixed.re
new file mode 100644
index 000000000..51f3b2b00
--- /dev/null
+++ b/tools/re2c/examples/input_custom/fixed.re
@@ -0,0 +1,35 @@
+// Build with "--input custom" re2c switch.
+//
+// This is an example of handling fixed-length buffer with "--input custom":
+// on each YYPEEK we check for the end of input, thus YYFILL generation
+// can be safely suppressed.
+//
+// Note that YYLIMIT points not to terminating NULL, but to the previous
+// character: we emulate the case when input has no terminating NULL.
+//
+// For a real-life example see https://github.com/sopyer/mjson
+// or mjson.re from re2c test collection.
+
+bool lex (const char * cursor, const char * const limit)
+{
+ const char * marker;
+ const char * ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() (cursor >= limit ? 0 : *cursor)
+# define YYSKIP() ++cursor
+# define YYBACKUP() marker = cursor
+# define YYBACKUPCTX() ctxmarker = cursor
+# define YYRESTORE() cursor = marker
+# define YYRESTORECTX() cursor = ctxmarker
+ /*!re2c
+ re2c:yyfill:enable = 0;
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ char buffer [] = "int buffer [1024]";
+ return !lex (buffer, buffer + sizeof (buffer) - 1);
+}
diff --git a/tools/re2c/examples/input_custom/simple/README b/tools/re2c/examples/input_custom/simple/README
new file mode 100644
index 000000000..c0c4d955a
--- /dev/null
+++ b/tools/re2c/examples/input_custom/simple/README
@@ -0,0 +1,20 @@
+Build with "--input custom" re2c switch.
+
+These are three examples of "--input custom" usage:
+
+- input_custom_default.re:
+ implements default re2c input model (pointers to plain buffer)
+
+- input_custom_fgetc:
+ implements C-style file input (using )
+
+- input_custom_fgetc:
+ implements std::istringstream input
+
+Note that these examples are very simple and don't need
+to implement YYFILL; the only reason they don't use
+"re2c:yyfill:enable = 0;" is to keep YYLESSTHAN and YYLIMIT
+(for the sake of example).
+
+In real-life programs one will need to care for correct
+end-of-input handling.
diff --git a/tools/re2c/examples/input_custom/simple/default.re b/tools/re2c/examples/input_custom/simple/default.re
new file mode 100644
index 000000000..94cde7cd6
--- /dev/null
+++ b/tools/re2c/examples/input_custom/simple/default.re
@@ -0,0 +1,24 @@
+bool lex (const char * cursor, const char * const limit)
+{
+ const char * marker;
+ const char * ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() *cursor
+# define YYSKIP() ++cursor
+# define YYBACKUP() marker = cursor
+# define YYBACKUPCTX() ctxmarker = cursor
+# define YYRESTORE() cursor = marker
+# define YYRESTORECTX() cursor = ctxmarker
+# define YYLESSTHAN(n) limit - cursor < n
+# define YYFILL(n) {}
+ /*!re2c
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ char buffer [] = "int buffer [1024]";
+ return !lex (buffer, buffer + sizeof (buffer));
+}
diff --git a/tools/re2c/examples/input_custom/simple/fgetc.re b/tools/re2c/examples/input_custom/simple/fgetc.re
new file mode 100644
index 000000000..d2dffd9a5
--- /dev/null
+++ b/tools/re2c/examples/input_custom/simple/fgetc.re
@@ -0,0 +1,43 @@
+#include
+
+char peek (FILE * f)
+{
+ char c = fgetc (f);
+ ungetc (c, f);
+ return c;
+}
+
+bool lex (FILE * f, const long limit)
+{
+ long marker;
+ long ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() peek (f)
+# define YYSKIP() fgetc (f)
+# define YYBACKUP() marker = ftell (f)
+# define YYBACKUPCTX() ctxmarker = ftell (f)
+# define YYRESTORE() fseek (f, marker, SEEK_SET)
+# define YYRESTORECTX() fseek (f, ctxmarker, SEEK_SET)
+# define YYLESSTHAN(n) limit - ftell (f) < n
+# define YYFILL(n) {}
+ /*!re2c
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ const char buffer [] = "int buffer [1024]";
+ const char fn [] = "input.txt";
+
+ FILE * f = fopen (fn, "w");
+ fwrite (buffer, 1, sizeof (buffer), f);
+ fclose (f);
+
+ f = fopen (fn, "rb");
+ int result = !lex (f, sizeof (buffer));
+ fclose (f);
+
+ return result;
+}
diff --git a/tools/re2c/examples/input_custom/simple/istringstream.re b/tools/re2c/examples/input_custom/simple/istringstream.re
new file mode 100644
index 000000000..5d702291e
--- /dev/null
+++ b/tools/re2c/examples/input_custom/simple/istringstream.re
@@ -0,0 +1,27 @@
+#include
+
+bool lex (std::istringstream & is, const std::streampos limit)
+{
+ std::streampos marker;
+ std::streampos ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() is.peek ()
+# define YYSKIP() is.ignore ()
+# define YYBACKUP() marker = is.tellg ()
+# define YYBACKUPCTX() ctxmarker = is.tellg ()
+# define YYRESTORE() is.seekg (marker)
+# define YYRESTORECTX() is.seekg (ctxmarker)
+# define YYLESSTHAN(n) limit - is.tellg () < n
+# define YYFILL(n) {}
+ /*!re2c
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ const char buffer [] = "int buffer [1024]";
+ std::istringstream is (buffer);
+ return !lex (is, sizeof (buffer));
+}
diff --git a/tools/re2c/examples/langs/c.re b/tools/re2c/examples/langs/c.re
new file mode 100644
index 000000000..7e413e2d0
--- /dev/null
+++ b/tools/re2c/examples/langs/c.re
@@ -0,0 +1,272 @@
+#include
+#include
+#include
+
+#define ADDEQ 257
+#define ANDAND 258
+#define ANDEQ 259
+#define ARRAY 260
+#define ASM 261
+#define AUTO 262
+#define BREAK 263
+#define CASE 264
+#define CHAR 265
+#define CONST 266
+#define CONTINUE 267
+#define DECR 268
+#define DEFAULT 269
+#define DEREF 270
+#define DIVEQ 271
+#define DO 272
+#define DOUBLE 273
+#define ELLIPSIS 274
+#define ELSE 275
+#define ENUM 276
+#define EQL 277
+#define EXTERN 278
+#define FCON 279
+#define FLOAT 280
+#define FOR 281
+#define FUNCTION 282
+#define GEQ 283
+#define GOTO 284
+#define ICON 285
+#define ID 286
+#define IF 287
+#define INCR 288
+#define INT 289
+#define LEQ 290
+#define LONG 291
+#define LSHIFT 292
+#define LSHIFTEQ 293
+#define MODEQ 294
+#define MULEQ 295
+#define NEQ 296
+#define OREQ 297
+#define OROR 298
+#define POINTER 299
+#define REGISTER 300
+#define RETURN 301
+#define RSHIFT 302
+#define RSHIFTEQ 303
+#define SCON 304
+#define SHORT 305
+#define SIGNED 306
+#define SIZEOF 307
+#define STATIC 308
+#define STRUCT 309
+#define SUBEQ 310
+#define SWITCH 311
+#define TYPEDEF 312
+#define UNION 313
+#define UNSIGNED 314
+#define VOID 315
+#define VOLATILE 316
+#define WHILE 317
+#define XOREQ 318
+#define EOI 319
+
+typedef unsigned int uint;
+typedef unsigned char uchar;
+
+#define BSIZE 8192
+
+#define YYCTYPE uchar
+#define YYCURSOR cursor
+#define YYLIMIT s->lim
+#define YYMARKER s->ptr
+#define YYFILL(n) {cursor = fill(s, cursor);}
+
+#define RET(i) {s->cur = cursor; return i;}
+
+typedef struct Scanner {
+ int fd;
+ uchar *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
+ uint line;
+} Scanner;
+
+uchar *fill(Scanner *s, uchar *cursor){
+ if(!s->eof) {
+ uint cnt = s->tok - s->bot;
+ if(cnt){
+ memcpy(s->bot, s->tok, s->lim - s->tok);
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ cursor -= cnt;
+ s->pos -= cnt;
+ s->lim -= cnt;
+ }
+ if((s->top - s->lim) < BSIZE){
+ uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
+ memcpy(buf, s->tok, s->lim - s->tok);
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ cursor = &buf[cursor - s->bot];
+ s->pos = &buf[s->pos - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ free(s->bot);
+ s->bot = buf;
+ }
+ if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
+ s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
+ }
+ s->lim += cnt;
+ }
+ return cursor;
+}
+
+int scan(Scanner *s){
+ uchar *cursor = s->cur;
+std:
+ s->tok = cursor;
+/*!re2c
+any = [\000-\377];
+O = [0-7];
+D = [0-9];
+L = [a-zA-Z_];
+H = [a-fA-F0-9];
+E = [Ee] [+-]? D+;
+FS = [fFlL];
+IS = [uUlL]*;
+ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
+*/
+
+/*!re2c
+ "/*" { goto comment; }
+
+ "auto" { RET(AUTO); }
+ "break" { RET(BREAK); }
+ "case" { RET(CASE); }
+ "char" { RET(CHAR); }
+ "const" { RET(CONST); }
+ "continue" { RET(CONTINUE); }
+ "default" { RET(DEFAULT); }
+ "do" { RET(DO); }
+ "double" { RET(DOUBLE); }
+ "else" { RET(ELSE); }
+ "enum" { RET(ENUM); }
+ "extern" { RET(EXTERN); }
+ "float" { RET(FLOAT); }
+ "for" { RET(FOR); }
+ "goto" { RET(GOTO); }
+ "if" { RET(IF); }
+ "int" { RET(INT); }
+ "long" { RET(LONG); }
+ "register" { RET(REGISTER); }
+ "return" { RET(RETURN); }
+ "short" { RET(SHORT); }
+ "signed" { RET(SIGNED); }
+ "sizeof" { RET(SIZEOF); }
+ "static" { RET(STATIC); }
+ "struct" { RET(STRUCT); }
+ "switch" { RET(SWITCH); }
+ "typedef" { RET(TYPEDEF); }
+ "union" { RET(UNION); }
+ "unsigned" { RET(UNSIGNED); }
+ "void" { RET(VOID); }
+ "volatile" { RET(VOLATILE); }
+ "while" { RET(WHILE); }
+
+ L (L|D)* { RET(ID); }
+
+ ("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
+ (['] (ESC|any\[\n\\'])* ['])
+ { RET(ICON); }
+
+ (D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
+ { RET(FCON); }
+
+ (["] (ESC|any\[\n\\"])* ["])
+ { RET(SCON); }
+
+ "..." { RET(ELLIPSIS); }
+ ">>=" { RET(RSHIFTEQ); }
+ "<<=" { RET(LSHIFTEQ); }
+ "+=" { RET(ADDEQ); }
+ "-=" { RET(SUBEQ); }
+ "*=" { RET(MULEQ); }
+ "/=" { RET(DIVEQ); }
+ "%=" { RET(MODEQ); }
+ "&=" { RET(ANDEQ); }
+ "^=" { RET(XOREQ); }
+ "|=" { RET(OREQ); }
+ ">>" { RET(RSHIFT); }
+ "<<" { RET(LSHIFT); }
+ "++" { RET(INCR); }
+ "--" { RET(DECR); }
+ "->" { RET(DEREF); }
+ "&&" { RET(ANDAND); }
+ "||" { RET(OROR); }
+ "<=" { RET(LEQ); }
+ ">=" { RET(GEQ); }
+ "==" { RET(EQL); }
+ "!=" { RET(NEQ); }
+ ";" { RET(';'); }
+ "{" { RET('{'); }
+ "}" { RET('}'); }
+ "," { RET(','); }
+ ":" { RET(':'); }
+ "=" { RET('='); }
+ "(" { RET('('); }
+ ")" { RET(')'); }
+ "[" { RET('['); }
+ "]" { RET(']'); }
+ "." { RET('.'); }
+ "&" { RET('&'); }
+ "!" { RET('!'); }
+ "~" { RET('~'); }
+ "-" { RET('-'); }
+ "+" { RET('+'); }
+ "*" { RET('*'); }
+ "/" { RET('/'); }
+ "%" { RET('%'); }
+ "<" { RET('<'); }
+ ">" { RET('>'); }
+ "^" { RET('^'); }
+ "|" { RET('|'); }
+ "?" { RET('?'); }
+
+
+ [ \t\v\f]+ { goto std; }
+
+ "\n"
+ {
+ if(cursor == s->eof) RET(EOI);
+ s->pos = cursor; s->line++;
+ goto std;
+ }
+
+ any
+ {
+ printf("unexpected character: %c\n", *s->tok);
+ goto std;
+ }
+*/
+
+comment:
+/*!re2c
+ "*/" { goto std; }
+ "\n"
+ {
+ if(cursor == s->eof) RET(EOI);
+ s->tok = s->pos = cursor; s->line++;
+ goto comment;
+ }
+ any { goto comment; }
+*/
+}
+
+main(){
+ Scanner in;
+ int t;
+ memset((char*) &in, 0, sizeof(in));
+ in.fd = 0;
+ while((t = scan(&in)) != EOI){
+/*
+ printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
+ printf("%d\n", t);
+*/
+ }
+ close(in.fd);
+}
diff --git a/tools/re2c/examples/langs/modula.re b/tools/re2c/examples/langs/modula.re
new file mode 100644
index 000000000..186b0cc13
--- /dev/null
+++ b/tools/re2c/examples/langs/modula.re
@@ -0,0 +1,203 @@
+#include
+#include
+#include
+
+typedef unsigned int uint;
+typedef unsigned char uchar;
+
+#define BSIZE 8192
+
+#define YYCTYPE uchar
+#define YYCURSOR cursor
+#define YYLIMIT s->lim
+#define YYMARKER s->ptr
+#define YYCTXMARKER s->ctx
+#define YYFILL {cursor = fill(s, cursor);}
+
+#define RETURN(i) {s->cur = cursor; return i;}
+
+typedef struct Scanner {
+ int fd;
+ uchar *bot, *tok, *ptr, *ctx, *cur, *pos, *lim, *top, *eof;
+ uint line;
+} Scanner;
+
+uchar *fill(Scanner *s, uchar *cursor){
+ if(!s->eof){
+ uint cnt = s->tok - s->bot;
+ if(cnt){
+ memcpy(s->bot, s->tok, s->lim - s->tok);
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ cursor -= cnt;
+ s->pos -= cnt;
+ s->lim -= cnt;
+ }
+ if((s->top - s->lim) < BSIZE){
+ uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
+ memcpy(buf, s->tok, s->lim - s->tok);
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ cursor = &buf[cursor - s->bot];
+ s->pos = &buf[s->pos - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ free(s->bot);
+ s->bot = buf;
+ }
+ if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
+ s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
+ }
+ s->lim += cnt;
+ }
+ return cursor;
+}
+
+int scan(Scanner *s){
+ uchar *cursor = s->cur;
+ uint depth;
+std:
+ s->tok = cursor;
+/*!re2c
+any = [\000-\377];
+digit = [0-9];
+letter = [a-zA-Z];
+*/
+
+/*!re2c
+ "(*" { depth = 1; goto comment; }
+
+ digit + {RETURN(1);}
+ digit + / ".." {RETURN(1);}
+ [0-7] + "B" {RETURN(2);}
+ [0-7] + "C" {RETURN(3);}
+ digit [0-9A-F] * "H" {RETURN(4);}
+ digit + "." digit * ("E" ([+-]) ? digit +) ? {RETURN(5);}
+ ['] (any\[\n']) * ['] | ["] (any\[\n"]) * ["] {RETURN(6);}
+
+ "#" {RETURN(7);}
+ "&" {RETURN(8);}
+ "(" {RETURN(9);}
+ ")" {RETURN(10);}
+ "*" {RETURN(11);}
+ "+" {RETURN(12);}
+ "," {RETURN(13);}
+ "-" {RETURN(14);}
+ "." {RETURN(15);}
+ ".." {RETURN(16);}
+ "/" {RETURN(17);}
+ ":" {RETURN(18);}
+ ":=" {RETURN(19);}
+ ";" {RETURN(20);}
+ "<" {RETURN(21);}
+ "<=" {RETURN(22);}
+ "<>" {RETURN(23);}
+ "=" {RETURN(24);}
+ ">" {RETURN(25);}
+ ">=" {RETURN(26);}
+ "[" {RETURN(27);}
+ "]" {RETURN(28);}
+ "^" {RETURN(29);}
+ "{" {RETURN(30);}
+ "|" {RETURN(31);}
+ "}" {RETURN(32);}
+ "~" {RETURN(33);}
+
+ "AND" {RETURN(34);}
+ "ARRAY" {RETURN(35);}
+ "BEGIN" {RETURN(36);}
+ "BY" {RETURN(37);}
+ "CASE" {RETURN(38);}
+ "CONST" {RETURN(39);}
+ "DEFINITION" {RETURN(40);}
+ "DIV" {RETURN(41);}
+ "DO" {RETURN(42);}
+ "ELSE" {RETURN(43);}
+ "ELSIF" {RETURN(44);}
+ "END" {RETURN(45);}
+ "EXIT" {RETURN(46);}
+ "EXPORT" {RETURN(47);}
+ "FOR" {RETURN(48);}
+ "FROM" {RETURN(49);}
+ "IF" {RETURN(50);}
+ "IMPLEMENTATION" {RETURN(51);}
+ "IMPORT" {RETURN(52);}
+ "IN" {RETURN(53);}
+ "LOOP" {RETURN(54);}
+ "MOD" {RETURN(55);}
+ "MODULE" {RETURN(56);}
+ "NOT" {RETURN(57);}
+ "OF" {RETURN(58);}
+ "OR" {RETURN(59);}
+ "POINTER" {RETURN(60);}
+ "PROCEDURE" {RETURN(61);}
+ "QUALIFIED" {RETURN(62);}
+ "RECORD" {RETURN(63);}
+ "REPEAT" {RETURN(64);}
+ "RETURN" {RETURN(65);}
+ "SET" {RETURN(66);}
+ "THEN" {RETURN(67);}
+ "TO" {RETURN(68);}
+ "TYPE" {RETURN(69);}
+ "UNTIL" {RETURN(70);}
+ "VAR" {RETURN(71);}
+ "WHILE" {RETURN(72);}
+ "WITH" {RETURN(73);}
+
+ letter (letter | digit) * {RETURN(74);}
+
+ [ \t]+ { goto std; }
+
+ "\n"
+ {
+ if(cursor == s->eof) RETURN(0);
+ s->pos = cursor; s->line++;
+ goto std;
+ }
+
+ any
+ {
+ printf("unexpected character: %c\n", *s->tok);
+ goto std;
+ }
+*/
+comment:
+/*!re2c
+ "*)"
+ {
+ if(--depth == 0)
+ goto std;
+ else
+ goto comment;
+ }
+ "(*" { ++depth; goto comment; }
+ "\n"
+ {
+ if(cursor == s->eof) RETURN(0);
+ s->tok = s->pos = cursor; s->line++;
+ goto comment;
+ }
+ any { goto comment; }
+*/
+}
+
+/*
+void putStr(FILE *o, char *s, uint l){
+ while(l-- > 0)
+ putc(*s++, o);
+}
+*/
+
+main(){
+ Scanner in;
+ memset((char*) &in, 0, sizeof(in));
+ in.fd = 0;
+ while(scan(&in)){
+/*
+ putc('<', stdout);
+ putStr(stdout, (char*) in.tok, in.cur - in.tok);
+ putc('>', stdout);
+ putc('\n', stdout);
+*/
+ }
+}
diff --git a/tools/re2c/examples/langs/rexx.re b/tools/re2c/examples/langs/rexx.re
new file mode 100644
index 000000000..b74741daf
--- /dev/null
+++ b/tools/re2c/examples/langs/rexx.re
@@ -0,0 +1,319 @@
+#include "scanio.h"
+#include "scanner.h"
+
+#define CURSOR ch
+#define LOADCURSOR ch = *cursor;
+#define ADVANCE cursor++;
+#define BACK(n) cursor -= (n);
+#define CHECK(n) if((ScanCB.lim - cursor) < (n)){cursor = ScanFill(cursor);}
+#define MARK(n) ScanCB.ptr = cursor; sel = (n);
+#define REVERT cursor = ScanCB.ptr;
+#define MARKER sel
+
+#define RETURN(i) {ScanCB.cur = cursor; return i;}
+
+int ScanToken(){
+ uchar *cursor = ScanCB.cur;
+ unsigned sel;
+ uchar ch;
+ ScanCB.tok = cursor;
+ ScanCB.eot = NULL;
+/*!re2c
+all = [\000-\377];
+eof = [\000];
+any = all\eof;
+letter = [a-z]|[A-Z];
+digit = [0-9];
+symchr = letter|digit|[.!?_];
+const = (digit|[.])symchr*([eE][+-]?digit+)?;
+simple = (symchr\(digit|[.]))(symchr\[.])*;
+stem = simple [.];
+symbol = symchr*;
+sqstr = ['] ((any\['\n])|(['][']))* ['];
+dqstr = ["] ((any\["\n])|(["]["]))* ["];
+str = sqstr|dqstr;
+ob = [ \t]*;
+not = [\\~];
+A = [aA];
+B = [bB];
+C = [cC];
+D = [dD];
+E = [eE];
+F = [fF];
+G = [gG];
+H = [hH];
+I = [iI];
+J = [jJ];
+K = [kK];
+L = [lL];
+M = [mM];
+N = [nN];
+O = [oO];
+P = [pP];
+Q = [qQ];
+R = [rR];
+S = [sS];
+T = [tT];
+U = [uU];
+V = [vV];
+W = [wW];
+X = [xX];
+Y = [yY];
+Z = [zZ];
+*/
+
+scan:
+/*!re2c
+"\n"
+ {
+ ++(ScanCB.lineNum);
+ ScanCB.linePos = ScanCB.pos + (cursor - ScanCB.mrk);
+ RETURN(SU_EOL);
+ }
+"|" ob "|"
+ { RETURN(OP_CONCAT); }
+"+"
+ { RETURN(OP_PLUS); }
+"-"
+ { RETURN(OP_MINUS); }
+"*"
+ { RETURN(OP_MULT); }
+"/"
+ { RETURN(OP_DIV); }
+"%"
+ { RETURN(OP_IDIV); }
+"/" ob "/"
+ { RETURN(OP_REMAIN); }
+"*" ob "*"
+ { RETURN(OP_POWER); }
+"="
+ { RETURN(OP_EQUAL); }
+not ob "=" | "<" ob ">" | ">" ob "<"
+ { RETURN(OP_EQUAL_N); }
+">"
+ { RETURN(OP_GT); }
+"<"
+ { RETURN(OP_LT); }
+">" ob "=" | not ob "<"
+ { RETURN(OP_GE); }
+"<" ob "=" | not ob ">"
+ { RETURN(OP_LE); }
+"=" ob "="
+ { RETURN(OP_EQUAL_EQ); }
+not ob "=" ob "="
+ { RETURN(OP_EQUAL_EQ_N); }
+">" ob ">"
+ { RETURN(OP_GT_STRICT); }
+"<" ob "<"
+ { RETURN(OP_LT_STRICT); }
+">" ob ">" ob "=" | not ob "<" ob "<"
+ { RETURN(OP_GE_STRICT); }
+"<" ob "<" ob "=" | not ob ">" ob ">"
+ { RETURN(OP_LE_STRICT); }
+"&"
+ { RETURN(OP_AND); }
+"|"
+ { RETURN(OP_OR); }
+"&" ob "&"
+ { RETURN(OP_XOR); }
+not
+ { RETURN(OP_NOT); }
+
+":"
+ { RETURN(SU_COLON); }
+","
+ { RETURN(SU_COMMA); }
+"("
+ { RETURN(SU_POPEN); }
+")"
+ { RETURN(SU_PCLOSE); }
+";"
+ { RETURN(SU_EOC); }
+
+A D D R E S S
+ { RETURN(RX_ADDRESS); }
+A R G
+ { RETURN(RX_ARG); }
+C A L L
+ { RETURN(RX_CALL); }
+D O
+ { RETURN(RX_DO); }
+D R O P
+ { RETURN(RX_DROP); }
+E L S E
+ { RETURN(RX_ELSE); }
+E N D
+ { RETURN(RX_END); }
+E X I T
+ { RETURN(RX_EXIT); }
+I F
+ { RETURN(RX_IF); }
+I N T E R P R E T
+ { RETURN(RX_INTERPRET); }
+I T E R A T E
+ { RETURN(RX_ITERATE); }
+L E A V E
+ { RETURN(RX_LEAVE); }
+N O P
+ { RETURN(RX_NOP); }
+N U M E R I C
+ { RETURN(RX_NUMERIC); }
+O P T I O N S
+ { RETURN(RX_OPTIONS); }
+O T H E R W I S E
+ { RETURN(RX_OTHERWISE); }
+P A R S E
+ { RETURN(RX_PARSE); }
+P R O C E D U R E
+ { RETURN(RX_PROCEDURE); }
+P U L L
+ { RETURN(RX_PULL); }
+P U S H
+ { RETURN(RX_PUSH); }
+Q U E U E
+ { RETURN(RX_QUEUE); }
+R E T U R N
+ { RETURN(RX_RETURN); }
+S A Y
+ { RETURN(RX_SAY); }
+S E L E C T
+ { RETURN(RX_SELECT); }
+S I G N A L
+ { RETURN(RX_SIGNAL); }
+T H E N
+ { RETURN(RX_THEN); }
+T R A C E
+ { RETURN(RX_TRACE); }
+W H E N
+ { RETURN(RX_WHEN); }
+O F F
+ { RETURN(RXS_OFF); }
+O N
+ { RETURN(RXS_ON); }
+B Y
+ { RETURN(RXS_BY); }
+D I G I T S
+ { RETURN(RXS_DIGITS); }
+E N G I N E E R I N G
+ { RETURN(RXS_ENGINEERING); }
+E R R O R
+ { RETURN(RXS_ERROR); }
+E X P O S E
+ { RETURN(RXS_EXPOSE); }
+F A I L U R E
+ { RETURN(RXS_FAILURE); }
+F O R
+ { RETURN(RXS_FOR); }
+F O R E V E R
+ { RETURN(RXS_FOREVER); }
+F O R M
+ { RETURN(RXS_FORM); }
+F U Z Z
+ { RETURN(RXS_FUZZ); }
+H A L T
+ { RETURN(RXS_HALT); }
+L I N E I N
+ { RETURN(RXS_LINEIN); }
+N A M E
+ { RETURN(RXS_NAME); }
+N O T R E A D Y
+ { RETURN(RXS_NOTREADY); }
+N O V A L U E
+ { RETURN(RXS_NOVALUE); }
+S C I E N T I F I C
+ { RETURN(RXS_SCIENTIFIC); }
+S O U R C E
+ { RETURN(RXS_SOURCE); }
+S Y N T A X
+ { RETURN(RXS_SYNTAX); }
+T O
+ { RETURN(RXS_TO); }
+U N T I L
+ { RETURN(RXS_UNTIL); }
+U P P E R
+ { RETURN(RXS_UPPER); }
+V A L U E
+ { RETURN(RXS_VALUE); }
+V A R
+ { RETURN(RXS_VAR); }
+V E R S I O N
+ { RETURN(RXS_VERSION); }
+W H I L E
+ { RETURN(RXS_WHILE); }
+W I T H
+ { RETURN(RXS_WITH); }
+
+const
+ { RETURN(SU_CONST); }
+simple
+ { RETURN(SU_SYMBOL); }
+stem
+ { RETURN(SU_SYMBOL_STEM); }
+symbol
+ { RETURN(SU_SYMBOL_COMPOUND); }
+str
+ { RETURN(SU_LITERAL); }
+str [bB] / (all\symchr)
+ { RETURN(SU_LITERAL_BIN); }
+str [xX] / (all\symchr)
+ { RETURN(SU_LITERAL_HEX); }
+
+eof
+ { RETURN(SU_EOF); }
+any
+ { RETURN(SU_ERROR); }
+*/
+}
+
+bool StripToken(){
+ uchar *cursor = ScanCB.cur;
+ unsigned depth;
+ uchar ch;
+ bool blanks = FALSE;
+ ScanCB.eot = cursor;
+strip:
+/*!re2c
+"/*"
+ {
+ depth = 1;
+ goto comment;
+ }
+"\r"
+ { goto strip; }
+[ \t]
+ {
+ blanks = TRUE;
+ goto strip;
+ }
+[] / all
+ { RETURN(blanks); }
+*/
+
+comment:
+/*!re2c
+"*/"
+ {
+ if(--depth == 0)
+ goto strip;
+ else
+ goto comment;
+ }
+"\n"
+ {
+ ++(ScanCB.lineNum);
+ ScanCB.linePos = ScanCB.pos + (cursor - ScanCB.mrk);
+ goto comment;
+ }
+"/*"
+ {
+ ++depth;
+ goto comment;
+ }
+eof
+ { RETURN(blanks); }
+any
+ {
+ goto comment;
+ }
+*/
+}
diff --git a/tools/re2c/examples/push_model/push.re b/tools/re2c/examples/push_model/push.re
new file mode 100644
index 000000000..5ad6e7ac8
--- /dev/null
+++ b/tools/re2c/examples/push_model/push.re
@@ -0,0 +1,340 @@
+/*
+ * A push-model scanner example for re2c -f
+ * Written Mon Apr 11 2005 by mgix@mgix.com
+ * This file is in the public domain.
+ *
+ */
+
+// ----------------------------------------------------------------------
+
+#include
+#include
+#include
+#include
+#include
+
+#if defined(WIN32)
+
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+#else
+
+ #include
+ #include
+
+ #ifndef O_BINARY
+ #define O_BINARY 0
+ #endif
+
+#endif
+
+// ----------------------------------------------------------------------
+#define TOKENS \
+ \
+ TOK(kEOF) \
+ TOK(kEOL) \
+ TOK(kUnknown) \
+ TOK(kIdentifier) \
+ TOK(kDecimalConstant) \
+ \
+ TOK(kEqual) \
+ TOK(kLeftParen) \
+ TOK(kRightParen) \
+ TOK(kMinus) \
+ TOK(kPlus) \
+ TOK(kStar) \
+ TOK(kSlash) \
+ \
+ TOK(kIf) \
+ TOK(kFor) \
+ TOK(kElse) \
+ TOK(kGoto) \
+ TOK(kBreak) \
+ TOK(kWhile) \
+ TOK(kReturn) \
+
+
+// ----------------------------------------------------------------------
+static const char *tokenNames[] =
+{
+ #define TOK(x) #x,
+ TOKENS
+ #undef TOK
+};
+
+// ----------------------------------------------------------------------
+class PushScanner
+{
+public:
+
+ enum Token
+ {
+ #define TOK(x) x,
+ TOKENS
+ #undef TOK
+ };
+
+private:
+
+ bool eof;
+ int32_t state;
+
+ uint8_t *limit;
+ uint8_t *start;
+ uint8_t *cursor;
+ uint8_t *marker;
+
+ uint8_t *buffer;
+ uint8_t *bufferEnd;
+
+ uint8_t yych;
+ uint32_t yyaccept;
+
+public:
+
+ // ----------------------------------------------------------------------
+ PushScanner()
+ {
+ limit = 0;
+ start = 0;
+ state = -1;
+ cursor = 0;
+ marker = 0;
+ buffer = 0;
+ eof = false;
+ bufferEnd = 0;
+ }
+
+ // ----------------------------------------------------------------------
+ ~PushScanner()
+ {
+ }
+
+ // ----------------------------------------------------------------------
+ void send(
+ Token token
+ )
+ {
+ size_t tokenSize = cursor-start;
+ const char *tokenName = tokenNames[token];
+ printf(
+ "scanner is pushing out a token of type %d (%s)",
+ token,
+ tokenName
+ );
+
+ if(token==kEOF) putchar('\n');
+ else
+ {
+ size_t tokenNameSize = strlen(tokenNames[token]);
+ size_t padSize = 20-(20");
+
+ fwrite(
+ start,
+ tokenSize,
+ 1,
+ stdout
+ );
+
+ printf("<----\n");
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ uint32_t push(
+ const void *input,
+ ssize_t inputSize
+ )
+ {
+ printf(
+ "scanner is receiving a new data batch of length %d\n"
+ "scanner continues with saved state = %d\n",
+ inputSize,
+ state
+ );
+
+ /*
+ * Data source is signaling end of file when batch size
+ * is less than maxFill. This is slightly annoying because
+ * maxFill is a value that can only be known after re2c does
+ * its thing. Practically though, maxFill is never bigger than
+ * the longest keyword, so given our grammar, 32 is a safe bet.
+ */
+ uint8_t null[64];
+ const ssize_t maxFill = 32;
+ if(inputSize // min
+#include // memset
+
+#include "src/codegen/bitmap.h"
+#include "src/codegen/go.h"
+#include "src/codegen/output.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+
+namespace re2c
+{
+
+BitMap *BitMap::first = NULL;
+
+BitMap::BitMap(const Go *g, const State *x)
+ : go(g)
+ , on(x)
+ , next(first)
+ , i(0)
+ , m(0)
+{
+ first = this;
+}
+
+BitMap::~BitMap()
+{
+ delete next;
+}
+
+const BitMap *BitMap::find(const Go *g, const State *x)
+{
+ for (const BitMap *b = first; b; b = b->next)
+ {
+ if (matches(b->go->span, b->go->nSpans, b->on, g->span, g->nSpans, x))
+ {
+ return b;
+ }
+ }
+
+ return new BitMap(g, x);
+}
+
+const BitMap *BitMap::find(const State *x)
+{
+ for (const BitMap *b = first; b; b = b->next)
+ {
+ if (b->on == x)
+ {
+ return b;
+ }
+ }
+
+ return NULL;
+}
+
+static void doGen(const Go *g, const State *s, uint32_t *bm, uint32_t f, uint32_t m)
+{
+ Span *b = g->span, *e = &b[g->nSpans];
+ uint32_t lb = 0;
+
+ for (; b < e; ++b)
+ {
+ if (b->to == s)
+ {
+ for (; lb < b->ub && lb < 256; ++lb)
+ {
+ bm[lb-f] |= m;
+ }
+ }
+
+ lb = b->ub;
+ }
+}
+
+void BitMap::gen(OutputFile & o, uint32_t ind, uint32_t lb, uint32_t ub)
+{
+ if (first && bUsedYYBitmap)
+ {
+ o.wind(ind).ws("static const unsigned char ").wstring(opts->yybm).ws("[] = {");
+
+ uint32_t c = 1, n = ub - lb;
+ const BitMap *cb = first;
+
+ while((cb = cb->next) != NULL) {
+ ++c;
+ }
+ BitMap *b = first;
+
+ uint32_t *bm = new uint32_t[n];
+
+ for (uint32_t i = 0, t = 1; b; i += n, t += 8)
+ {
+ memset(bm, 0, n * sizeof(uint32_t));
+
+ for (uint32_t m = 0x80; b && m; m >>= 1)
+ {
+ b->i = i;
+ b->m = m;
+ doGen(b->go, b->on, bm, lb, m);
+ b = const_cast(b->next);
+ }
+
+ if (c > 8)
+ {
+ o.ws("\n").wind(ind+1).ws("/* table ").wu32(t).ws(" .. ").wu32(std::min(c, t+7)).ws(": ").wu32(i).ws(" */");
+ }
+
+ for (uint32_t j = 0; j < n; ++j)
+ {
+ if (j % 8 == 0)
+ {
+ o.ws("\n").wind(ind+1);
+ }
+
+ if (opts->yybmHexTable)
+ {
+ o.wu32_hex(bm[j]);
+ }
+ else
+ {
+ o.wu32_width(bm[j], 3);
+ }
+ o.ws(", ");
+ }
+ }
+
+ o.ws("\n").wind(ind).ws("};\n");
+
+ delete[] bm;
+ }
+}
+
+// All spans in b1 that lead to s1 are pairwise equal to that in b2 leading to s2
+bool matches(const Span * b1, uint32_t n1, const State * s1, const Span * b2, uint32_t n2, const State * s2)
+{
+ const Span * e1 = &b1[n1];
+ uint32_t lb1 = 0;
+ const Span * e2 = &b2[n2];
+ uint32_t 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 false;
+ }
+ if (lb1 != lb2 || b1->ub != b2->ub)
+ {
+ return false;
+ }
+ ++b1;
+ ++b2;
+ }
+}
+
+} // end namespace re2c
diff --git a/tools/re2c/src/codegen/bitmap.h b/tools/re2c/src/codegen/bitmap.h
new file mode 100644
index 000000000..17d7a852b
--- /dev/null
+++ b/tools/re2c/src/codegen/bitmap.h
@@ -0,0 +1,45 @@
+#ifndef _RE2C_CODEGEN_BITMAP_
+#define _RE2C_CODEGEN_BITMAP_
+
+#include "src/util/c99_stdint.h"
+
+#include "src/util/forbid_copy.h"
+
+namespace re2c
+{
+
+struct Go;
+struct Span;
+struct State;
+struct OutputFile;
+
+class BitMap
+{
+public:
+ static BitMap *first;
+
+ const Go *go;
+ const State *on;
+ const BitMap *next;
+ uint32_t i;
+ uint32_t m;
+
+public:
+ static const BitMap *find(const Go*, const State*);
+ static const BitMap *find(const State*);
+ static void gen(OutputFile &, uint32_t ind, uint32_t, uint32_t);
+ BitMap(const Go*, const State*);
+ ~BitMap();
+
+ FORBID_COPY (BitMap);
+};
+
+bool matches(const Span * b1, uint32_t n1, const State * s1, const Span * b2, uint32_t n2, const State * s2);
+
+#ifdef _MSC_VER
+# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
+#endif
+
+} // end namespace re2c
+
+#endif // _RE2C_CODEGEN_BITMAP_
diff --git a/tools/re2c/src/codegen/emit.h b/tools/re2c/src/codegen/emit.h
new file mode 100644
index 000000000..5d91b14e9
--- /dev/null
+++ b/tools/re2c/src/codegen/emit.h
@@ -0,0 +1,43 @@
+#ifndef _RE2C_CODEGEN_EMIT_
+#define _RE2C_CODEGEN_EMIT_
+
+#include "src/codegen/output.h"
+#include "src/ir/adfa/adfa.h"
+
+namespace re2c {
+
+typedef std::vector RegExpIndices;
+
+void emit_action
+ ( const Action & action
+ , OutputFile & o
+ , uint32_t ind
+ , bool & readCh
+ , const State * const s
+ , const std::string & condName
+ , const Skeleton * skeleton
+ , const std::set & used_labels
+ , bool save_yyaccept
+ );
+
+// helpers
+void genGoTo (OutputFile & o, uint32_t ind, const State * from, const State * to, bool & readCh);
+
+template std::string replaceParam (std::string str, const std::string & param, const _Ty & value)
+{
+ if (!param.empty ())
+ {
+ std::ostringstream strValue;
+ strValue << value;
+ std::string::size_type pos;
+ while((pos = str.find(param)) != std::string::npos)
+ {
+ str.replace(pos, param.length(), strValue.str());
+ }
+ }
+ return str;
+}
+
+} // namespace re2c
+
+#endif // _RE2C_CODEGEN_EMIT_
diff --git a/tools/re2c/src/codegen/emit_action.cc b/tools/re2c/src/codegen/emit_action.cc
new file mode 100644
index 000000000..d3146daef
--- /dev/null
+++ b/tools/re2c/src/codegen/emit_action.cc
@@ -0,0 +1,388 @@
+#include "src/util/c99_stdint.h"
+#include
+#include
+#include
+
+#include "src/codegen/emit.h"
+#include "src/codegen/input_api.h"
+#include "src/codegen/output.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+#include "src/ir/adfa/action.h"
+#include "src/ir/adfa/adfa.h"
+#include "src/ir/regexp/regexp.h"
+#include "src/ir/regexp/regexp_rule.h"
+#include "src/ir/skeleton/skeleton.h"
+#include "src/parse/code.h"
+#include "src/parse/loc.h"
+
+namespace re2c
+{
+
+class label_t;
+
+static void need (OutputFile & o, uint32_t ind, bool & readCh, size_t n, bool bSetMarker);
+static void emit_match (OutputFile & o, uint32_t ind, bool & readCh, const State * const s);
+static void emit_initial (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const Initial & init, const std::set & used_labels);
+static void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save, bool save_yyaccept);
+static void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept, size_t l, size_t r);
+static void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept);
+static void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName, const Skeleton * skeleton);
+static void genYYFill (OutputFile & o, size_t need);
+static void genSetCondition (OutputFile & o, uint32_t ind, const std::string & newcond);
+static void genSetState (OutputFile & o, uint32_t ind, uint32_t fillIndex);
+
+void emit_action
+ ( const Action & action
+ , OutputFile & o
+ , uint32_t ind
+ , bool & readCh
+ , const State * const s
+ , const std::string & condName
+ , const Skeleton * skeleton
+ , const std::set & used_labels
+ , bool save_yyaccept
+ )
+{
+ switch (action.type)
+ {
+ case Action::MATCH:
+ emit_match (o, ind, readCh, s);
+ break;
+ case Action::INITIAL:
+ emit_initial (o, ind, readCh, s, * action.info.initial, used_labels);
+ break;
+ case Action::SAVE:
+ emit_save (o, ind, readCh, s, action.info.save, save_yyaccept);
+ break;
+ case Action::MOVE:
+ break;
+ case Action::ACCEPT:
+ emit_accept (o, ind, readCh, s, * action.info.accepts);
+ break;
+ case Action::RULE:
+ emit_rule (o, ind, s, action.info.rule, condName, skeleton);
+ break;
+ }
+ if (s->isPreCtxt && opts->target != opt_t::DOT)
+ {
+ o.wstring(opts->input_api.stmt_backupctx (ind));
+ }
+}
+
+void emit_match (OutputFile & o, uint32_t ind, bool & readCh, const State * const s)
+{
+ if (opts->target == opt_t::DOT)
+ {
+ return;
+ }
+
+ const bool read_ahead = s
+ && s->next
+ && s->next->action.type != Action::RULE;
+ if (s->fill != 0)
+ {
+ o.wstring(opts->input_api.stmt_skip (ind));
+ }
+ else if (!read_ahead)
+ {
+ /* do not read next char if match */
+ o.wstring(opts->input_api.stmt_skip (ind));
+ readCh = true;
+ }
+ else
+ {
+ o.wstring(opts->input_api.stmt_skip_peek (ind));
+ readCh = false;
+ }
+
+ if (s->fill != 0)
+ {
+ need(o, ind, readCh, s->fill, false);
+ }
+}
+
+void emit_initial (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const Initial & initial, const std::set & used_labels)
+{
+ if (opts->target == opt_t::DOT)
+ {
+ return;
+ }
+
+ if (used_labels.count(s->label))
+ {
+ if (s->fill != 0)
+ {
+ o.wstring(opts->input_api.stmt_skip (ind));
+ }
+ else
+ {
+ o.wstring(opts->input_api.stmt_skip_peek (ind));
+ }
+ }
+
+ if (used_labels.count(initial.label))
+ {
+ o.wstring(opts->labelPrefix).wlabel(initial.label).ws(":\n");
+ }
+
+ if (opts->dFlag)
+ {
+ o.wind(ind).wstring(opts->yydebug).ws("(").wlabel(initial.label).ws(", *").wstring(opts->yycursor).ws(");\n");
+ }
+
+ if (s->fill != 0)
+ {
+ need(o, ind, readCh, s->fill, initial.setMarker);
+ }
+ else
+ {
+ if (initial.setMarker)
+ {
+ o.wstring(opts->input_api.stmt_backup (ind));
+ }
+ readCh = false;
+ }
+}
+
+void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save, bool save_yyaccept)
+{
+ if (opts->target == opt_t::DOT)
+ {
+ return;
+ }
+
+ if (save_yyaccept)
+ {
+ o.wind(ind).wstring(opts->yyaccept).ws(" = ").wu32(save).ws(";\n");
+ }
+
+ if (s->fill != 0)
+ {
+ o.wstring(opts->input_api.stmt_skip_backup (ind));
+ need(o, ind, readCh, s->fill, false);
+ }
+ else
+ {
+ o.wstring(opts->input_api.stmt_skip_backup_peek (ind));
+ readCh = false;
+ }
+}
+
+void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accepts, size_t l, size_t r)
+{
+ if (l < r)
+ {
+ const size_t m = (l + r) >> 1;
+ o.wind(ind).ws("if (").wstring(opts->yyaccept).ws(r == l+1 ? " == " : " <= ").wu64(m).ws(") {\n");
+ emit_accept_binary (o, ++ind, readCh, s, accepts, l, m);
+ o.wind(--ind).ws("} else {\n");
+ emit_accept_binary (o, ++ind, readCh, s, accepts, m + 1, r);
+ o.wind(--ind).ws("}\n");
+ }
+ else
+ {
+ genGoTo(o, ind, s, accepts[l], readCh);
+ }
+}
+
+void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accepts)
+{
+ const size_t accepts_size = accepts.size ();
+ if (accepts_size > 0)
+ {
+ if (opts->target != opt_t::DOT)
+ {
+ o.wstring(opts->input_api.stmt_restore (ind));
+ }
+
+ if (readCh) // shouldn't be necessary, but might become at some point
+ {
+ o.wstring(opts->input_api.stmt_peek (ind));
+ readCh = false;
+ }
+
+ if (accepts_size > 1)
+ {
+ if (opts->gFlag && accepts_size >= opts->cGotoThreshold)
+ {
+ o.wind(ind++).ws("{\n");
+ o.wind(ind++).ws("static void *").wstring(opts->yytarget).ws("[").wu64(accepts_size).ws("] = {\n");
+ for (uint32_t i = 0; i < accepts_size; ++i)
+ {
+ o.wind(ind).ws("&&").wstring(opts->labelPrefix).wlabel(accepts[i]->label).ws(",\n");
+ }
+ o.wind(--ind).ws("};\n");
+ o.wind(ind).ws("goto *").wstring(opts->yytarget).ws("[").wstring(opts->yyaccept).ws("];\n");
+ o.wind(--ind).ws("}\n");
+ }
+ else if (opts->sFlag || (accepts_size == 2 && opts->target != opt_t::DOT))
+ {
+ emit_accept_binary (o, ind, readCh, s, accepts, 0, accepts_size - 1);
+ }
+ else if (opts->target == opt_t::DOT)
+ {
+ for (uint32_t i = 0; i < accepts_size; ++i)
+ {
+ o.wlabel(s->label).ws(" -> ").wlabel(accepts[i]->label);
+ o.ws(" [label=\"yyaccept=").wu32(i).ws("\"]\n");
+ }
+ }
+ else
+ {
+ o.wind(ind).ws("switch (").wstring(opts->yyaccept).ws(") {\n");
+ for (uint32_t i = 0; i < accepts_size - 1; ++i)
+ {
+ o.wind(ind).ws("case ").wu32(i).ws(": \t");
+ genGoTo(o, 0, s, accepts[i], readCh);
+ }
+ o.wind(ind).ws("default:\t");
+ genGoTo(o, 0, s, accepts[accepts_size - 1], readCh);
+ o.wind(ind).ws("}\n");
+ }
+ }
+ else
+ {
+ // no need to write if statement here since there is only case 0.
+ genGoTo(o, ind, s, accepts[0], readCh);
+ }
+ }
+}
+
+void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName, const Skeleton * skeleton)
+{
+ if (opts->target == opt_t::DOT)
+ {
+ o.wlabel(s->label);
+ if (rule->code)
+ {
+ o.ws(" [label=\"").wstring(rule->code->loc.filename).ws(":").wu32(rule->code->loc.line).ws("\"]");
+ }
+ o.ws("\n");
+ return;
+ }
+
+ uint32_t back = rule->ctx->fixedLength();
+ if (back != 0u && opts->target != opt_t::DOT)
+ {
+ o.wstring(opts->input_api.stmt_restorectx (ind));
+ }
+
+ if (opts->target == opt_t::SKELETON)
+ {
+ skeleton->emit_action (o, ind, rule->rank);
+ }
+ else
+ {
+ if (!rule->newcond.empty () && condName != rule->newcond)
+ {
+ genSetCondition(o, ind, rule->newcond);
+ }
+
+ if (rule->code)
+ {
+ if (!yySetupRule.empty ())
+ {
+ o.wind(ind).wstring(yySetupRule).ws("\n");
+ }
+ o.wline_info(rule->code->loc.line, rule->code->loc.filename.c_str ())
+ .wind(ind).wstring(rule->code->text).ws("\n")
+ .wdelay_line_info ();
+ }
+ else if (!rule->newcond.empty ())
+ {
+ o.wind(ind).wstring(replaceParam(opts->condGoto, opts->condGotoParam, opts->condPrefix + rule->newcond)).ws("\n");
+ }
+ }
+}
+
+void need (OutputFile & o, uint32_t ind, bool & readCh, size_t n, bool bSetMarker)
+{
+ if (opts->target == opt_t::DOT)
+ {
+ return;
+ }
+
+ uint32_t fillIndex = last_fill_index;
+
+ if (opts->fFlag)
+ {
+ last_fill_index++;
+ genSetState (o, ind, fillIndex);
+ }
+
+ if (opts->fill_use && n > 0)
+ {
+ o.wind(ind);
+ if (n == 1)
+ {
+ if (opts->fill_check)
+ {
+ o.ws("if (").wstring(opts->input_api.expr_lessthan_one ()).ws(") ");
+ }
+ genYYFill(o, n);
+ }
+ else
+ {
+ if (opts->fill_check)
+ {
+ o.ws("if (").wstring(opts->input_api.expr_lessthan (n)).ws(") ");
+ }
+ genYYFill(o, n);
+ }
+ }
+
+ if (opts->fFlag)
+ {
+ o.wstring(opts->yyfilllabel).wu32(fillIndex).ws(":\n");
+ }
+
+ if (n > 0)
+ {
+ if (bSetMarker)
+ {
+ o.wstring(opts->input_api.stmt_backup_peek (ind));
+ }
+ else
+ {
+ o.wstring(opts->input_api.stmt_peek (ind));
+ }
+ readCh = false;
+ }
+}
+
+void genYYFill (OutputFile & o, size_t need)
+{
+ o.wstring(replaceParam (opts->fill, opts->fill_arg, need));
+ if (!opts->fill_naked)
+ {
+ if (opts->fill_arg_use)
+ {
+ o.ws("(").wu64(need).ws(")");
+ }
+ o.ws(";");
+ }
+ o.ws("\n");
+}
+
+void genSetCondition(OutputFile & o, uint32_t ind, const std::string& newcond)
+{
+ o.wind(ind).wstring(replaceParam (opts->cond_set, opts->cond_set_arg, opts->condEnumPrefix + newcond));
+ if (!opts->cond_set_naked)
+ {
+ o.ws("(").wstring(opts->condEnumPrefix).wstring(newcond).ws(");");
+ }
+ o.ws("\n");
+}
+
+void genSetState(OutputFile & o, uint32_t ind, uint32_t fillIndex)
+{
+ o.wind(ind).wstring(replaceParam (opts->state_set, opts->state_set_arg, fillIndex));
+ if (!opts->state_set_naked)
+ {
+ o.ws("(").wu32(fillIndex).ws(");");
+ }
+ o.ws("\n");
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/emit_dfa.cc b/tools/re2c/src/codegen/emit_dfa.cc
new file mode 100644
index 000000000..ce826d310
--- /dev/null
+++ b/tools/re2c/src/codegen/emit_dfa.cc
@@ -0,0 +1,348 @@
+#include "src/util/c99_stdint.h"
+#include
+#include
+#include
+#include
+#include
+
+#include "src/codegen/bitmap.h"
+#include "src/codegen/emit.h"
+#include "src/codegen/go.h"
+#include "src/codegen/input_api.h"
+#include "src/codegen/label.h"
+#include "src/codegen/output.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+#include "src/ir/adfa/action.h"
+#include "src/ir/adfa/adfa.h"
+#include "src/ir/skeleton/skeleton.h"
+#include "src/util/counter.h"
+
+namespace re2c
+{
+
+static std::string genGetCondition ();
+static void genCondGotoSub (OutputFile & o, uint32_t ind, const std::vector & condnames, uint32_t cMin, uint32_t cMax);
+static void genCondTable (OutputFile & o, uint32_t ind, const std::vector & condnames);
+static void genCondGoto (OutputFile & o, uint32_t ind, const std::vector & condnames);
+static void emit_state (OutputFile & o, uint32_t ind, const State * s, bool used_label);
+
+std::string genGetCondition()
+{
+ return opts->cond_get_naked
+ ? opts->cond_get
+ : opts->cond_get + "()";
+}
+
+void genGoTo(OutputFile & o, uint32_t ind, const State *from, const State *to, bool & readCh)
+{
+ if (opts->target == opt_t::DOT)
+ {
+ o.wlabel(from->label).ws(" -> ").wlabel(to->label).ws("\n");
+ return;
+ }
+
+ if (readCh && from->next != to)
+ {
+ o.wstring(opts->input_api.stmt_peek (ind));
+ readCh = false;
+ }
+
+ o.wind(ind).ws("goto ").wstring(opts->labelPrefix).wlabel(to->label).ws(";\n");
+}
+
+void emit_state (OutputFile & o, uint32_t ind, const State * s, bool used_label)
+{
+ if (opts->target != opt_t::DOT)
+ {
+ if (used_label)
+ {
+ o.wstring(opts->labelPrefix).wlabel(s->label).ws(":\n");
+ }
+ if (opts->dFlag && (s->action.type != Action::INITIAL))
+ {
+ o.wind(ind).wstring(opts->yydebug).ws("(").wlabel(s->label).ws(", ").wstring(opts->input_api.expr_peek ()).ws(");\n");
+ }
+ }
+}
+
+void DFA::count_used_labels (std::set & used, label_t start, label_t initial, bool force_start) const
+{
+ // In '-f' mode, default state is always state 0
+ if (opts->fFlag)
+ {
+ used.insert (label_t::first ());
+ }
+ if (force_start)
+ {
+ used.insert (start);
+ }
+ for (State * s = head; s; s = s->next)
+ {
+ s->go.used_labels (used);
+ }
+ for (uint32_t i = 0; i < accepts.size (); ++i)
+ {
+ used.insert (accepts[i]->label);
+ }
+ // must go last: it needs the set of used labels
+ if (used.count (head->label))
+ {
+ used.insert (initial);
+ }
+}
+
+void DFA::emit_body (OutputFile & o, uint32_t& ind, const std::set & used_labels, label_t initial) const
+{
+ // If DFA has transitions to initial state, then initial state
+ // has a piece of code that advances input position. Wee must
+ // skip it when entering DFA.
+ if (used_labels.count(head->label))
+ {
+ o.wind(ind).ws("goto ").wstring(opts->labelPrefix).wlabel(initial).ws(";\n");
+ }
+
+ const bool save_yyaccept = accepts.size () > 1;
+ for (State * s = head; s; s = s->next)
+ {
+ bool readCh = false;
+ emit_state (o, ind, s, used_labels.count (s->label) != 0);
+ emit_action (s->action, o, ind, readCh, s, cond, skeleton, used_labels, save_yyaccept);
+ s->go.emit(o, ind, readCh);
+ }
+}
+
+void DFA::emit(Output & output, uint32_t& ind, bool isLastCond, bool& bPrologBrace)
+{
+ OutputFile & o = output.source;
+
+ bool bProlog = (!opts->cFlag || !bWroteCondCheck);
+
+ // start_label points to the beginning of current re2c block
+ // (prior to condition dispatch in '-c' mode)
+ // it can forced by configuration 're2c:startlabel = ;'
+ label_t start_label = o.label_counter.next ();
+ // initial_label points to the beginning of DFA
+ // in '-c' mode this is NOT equal to start_label
+ label_t initial_label = bProlog && opts->cFlag
+ ? o.label_counter.next ()
+ : start_label;
+ for (State * s = head; s; s = s->next)
+ {
+ s->label = o.label_counter.next ();
+ }
+ std::set used_labels;
+ count_used_labels (used_labels, start_label, initial_label, o.get_force_start_label ());
+
+ head->action.set_initial (initial_label, head->action.type == Action::SAVE);
+
+ skeleton->warn_undefined_control_flow ();
+ skeleton->warn_unreachable_rules ();
+ skeleton->warn_match_empty ();
+
+ if (opts->target == opt_t::SKELETON)
+ {
+ if (output.skeletons.insert (name).second)
+ {
+ skeleton->emit_data (o.file_name);
+ skeleton->emit_start (o, max_fill, need_backup, need_backupctx, need_accept);
+ uint32_t i = 2;
+ emit_body (o, i, used_labels, initial_label);
+ skeleton->emit_end (o, need_backup, need_backupctx);
+ }
+ }
+ else
+ {
+ // Generate prolog
+ if (bProlog)
+ {
+ o.ws("\n").wdelay_line_info ();
+ if (opts->target == opt_t::DOT)
+ {
+ bPrologBrace = true;
+ o.ws("digraph re2c {\n");
+ }
+ else if ((!opts->fFlag && o.get_used_yyaccept ())
+ || (!opts->fFlag && opts->bEmitYYCh)
+ || (opts->bFlag && !opts->cFlag && BitMap::first)
+ || (opts->cFlag && !bWroteCondCheck && opts->gFlag)
+ || (opts->fFlag && !bWroteGetState && opts->gFlag)
+ )
+ {
+ bPrologBrace = true;
+ o.wind(ind++).ws("{\n");
+ }
+ else if (ind == 0)
+ {
+ ind = 1;
+ }
+ if (!opts->fFlag && opts->target != opt_t::DOT)
+ {
+ if (opts->bEmitYYCh)
+ {
+ o.wind(ind).wstring(opts->yyctype).ws(" ").wstring(opts->yych).ws(";\n");
+ }
+ o.wdelay_yyaccept_init (ind);
+ }
+ else
+ {
+ o.ws("\n");
+ }
+ }
+ if (opts->bFlag && !opts->cFlag && BitMap::first)
+ {
+ BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
+ }
+ if (bProlog)
+ {
+ if (opts->cFlag && !bWroteCondCheck && opts->gFlag)
+ {
+ genCondTable(o, ind, output.types);
+ }
+ o.wdelay_state_goto (ind);
+ if (opts->cFlag && opts->target != opt_t::DOT)
+ {
+ if (used_labels.count(start_label))
+ {
+ o.wstring(opts->labelPrefix).wlabel(start_label).ws(":\n");
+ }
+ }
+ o.wuser_start_label ();
+ if (opts->cFlag && !bWroteCondCheck)
+ {
+ genCondGoto(o, ind, output.types);
+ }
+ }
+ if (opts->cFlag && !cond.empty())
+ {
+ if (opts->condDivider.length())
+ {
+ o.wstring(replaceParam(opts->condDivider, opts->condDividerParam, cond)).ws("\n");
+ }
+ if (opts->target == opt_t::DOT)
+ {
+ o.wstring(cond).ws(" -> ").wlabel(head->label).ws("\n");
+ }
+ else
+ {
+ o.wstring(opts->condPrefix).wstring(cond).ws(":\n");
+ }
+ }
+ if (opts->cFlag && opts->bFlag && BitMap::first)
+ {
+ o.wind(ind++).ws("{\n");
+ BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
+ }
+ // Generate code
+ emit_body (o, ind, used_labels, initial_label);
+ if (opts->cFlag && opts->bFlag && BitMap::first)
+ {
+ o.wind(--ind).ws("}\n");
+ }
+ // Generate epilog
+ if ((!opts->cFlag || isLastCond) && bPrologBrace)
+ {
+ o.wind(--ind).ws("}\n");
+ }
+ }
+
+ // Cleanup
+ if (BitMap::first)
+ {
+ delete BitMap::first;
+ BitMap::first = NULL;
+ }
+}
+
+void genCondTable(OutputFile & o, uint32_t ind, const std::vector & condnames)
+{
+ const size_t conds = condnames.size ();
+ o.wind(ind++).ws("static void *").wstring(opts->yyctable).ws("[").wu64(conds).ws("] = {\n");
+ for (size_t i = 0; i < conds; ++i)
+ {
+ o.wind(ind).ws("&&").wstring(opts->condPrefix).wstring(condnames[i]).ws(",\n");
+ }
+ o.wind(--ind).ws("};\n");
+}
+
+void genCondGotoSub(OutputFile & o, uint32_t ind, const std::vector & condnames, uint32_t cMin, uint32_t cMax)
+{
+ if (cMin == cMax)
+ {
+ o.wind(ind).ws("goto ").wstring(opts->condPrefix).wstring(condnames[cMin]).ws(";\n");
+ }
+ else
+ {
+ uint32_t cMid = cMin + ((cMax - cMin + 1) / 2);
+
+ o.wind(ind).ws("if (").wstring(genGetCondition()).ws(" < ").wu32(cMid).ws(") {\n");
+ genCondGotoSub(o, ind + 1, condnames, cMin, cMid - 1);
+ o.wind(ind).ws("} else {\n");
+ genCondGotoSub(o, ind + 1, condnames, cMid, cMax);
+ o.wind(ind).ws("}\n");
+ }
+}
+
+/*
+ * note [condition order]
+ *
+ * In theory re2c makes no guarantee about the order of conditions in
+ * the generated lexer. Users should define condition type 'YYCONDTYPE'
+ * and use values of this type with 'YYGETCONDITION' and 'YYSETCONDITION'.
+ * This way code is independent of internal re2c condition numbering.
+ *
+ * However, it is possible to manually hardcode condition numbers and make
+ * re2c generate condition dispatch without explicit use of condition names
+ * (nested 'if' statements with '-b' or computed 'goto' table with '-g').
+ * This code is syntactically valid (compiles), but unsafe:
+ * - change of re2c options may break compilation
+ * - change of internal re2c condition numbering may break runtime
+ *
+ * re2c has to preserve the existing numbering scheme.
+ *
+ * re2c warns about implicit assumptions about condition order, unless:
+ * - condition type is defined with 'types:re2c' or '-t, --type-header'
+ * - dispatch is independent of condition order: either it uses
+ * explicit condition names or there's only one condition and
+ * dispatch shrinks to unconditional jump
+ */
+void genCondGoto(OutputFile & o, uint32_t ind, const std::vector & condnames)
+{
+ const size_t conds = condnames.size ();
+ if (opts->target == opt_t::DOT)
+ {
+ o.warn_condition_order = false; // see note [condition order]
+ for (size_t i = 0; i < conds; ++i)
+ {
+ const std::string cond = condnames[i];
+ o.ws("0 -> ").wstring(cond).ws(" [label=\"state=").wstring(cond).ws("\"]\n");
+ }
+ }
+ else if (opts->gFlag)
+ {
+ o.wind(ind).ws("goto *").wstring(opts->yyctable).ws("[").wstring(genGetCondition()).ws("];\n");
+ }
+ else if (opts->sFlag)
+ {
+ if (conds == 1)
+ {
+ o.warn_condition_order = false; // see note [condition order]
+ }
+ genCondGotoSub(o, ind, condnames, 0, static_cast (conds) - 1);
+ }
+ else
+ {
+ o.warn_condition_order = false; // see note [condition order]
+ o.wind(ind).ws("switch (").wstring(genGetCondition()).ws(") {\n");
+ for (size_t i = 0; i < conds; ++i)
+ {
+ const std::string & cond = condnames[i];
+ o.wind(ind).ws("case ").wstring(opts->condEnumPrefix).wstring(cond).ws(": goto ").wstring(opts->condPrefix).wstring(cond).ws(";\n");
+ }
+ o.wind(ind).ws("}\n");
+ }
+ o.wdelay_warn_condition_order ();
+ bWroteCondCheck = true;
+}
+
+} // end namespace re2c
diff --git a/tools/re2c/src/codegen/go.h b/tools/re2c/src/codegen/go.h
new file mode 100644
index 000000000..21f1be979
--- /dev/null
+++ b/tools/re2c/src/codegen/go.h
@@ -0,0 +1,216 @@
+#ifndef _RE2C_CODEGEN_GO_
+#define _RE2C_CODEGEN_GO_
+
+#include
+#include
+#include
+
+#include "src/codegen/output.h"
+#include "src/util/c99_stdint.h"
+#include "src/util/forbid_copy.h"
+
+namespace re2c
+{
+
+class BitMap;
+struct State;
+struct If;
+
+struct Span
+{
+ uint32_t ub;
+ State * to;
+
+ FORBID_COPY (Span);
+};
+
+struct Case
+{
+ std::vector > ranges;
+ const State * to;
+ void emit (OutputFile & o, uint32_t ind);
+
+ inline Case ()
+ : ranges ()
+ , to (NULL)
+ {}
+
+ FORBID_COPY (Case);
+};
+
+struct Cases
+{
+ const State * def;
+ Case * cases;
+ uint32_t cases_size;
+ void add (uint32_t lb, uint32_t ub, State * to);
+ Cases (const Span * s, uint32_t n);
+ ~Cases ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+
+ FORBID_COPY (Cases);
+};
+
+struct Cond
+{
+ std::string compare;
+ uint32_t value;
+ Cond (const std::string & cmp, uint32_t val);
+};
+
+struct Binary
+{
+ Cond * cond;
+ If * thn;
+ If * els;
+ Binary (const Span * s, uint32_t n, const State * next);
+ ~Binary ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+
+ FORBID_COPY (Binary);
+};
+
+struct Linear
+{
+ std::vector > branches;
+ Linear (const Span * s, uint32_t n, const State * next);
+ ~Linear ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+};
+
+struct If
+{
+ enum type_t
+ {
+ BINARY,
+ LINEAR
+ } type;
+ union
+ {
+ Binary * binary;
+ Linear * linear;
+ } info;
+ If (type_t t, const Span * sp, uint32_t nsp, const State * next);
+ ~If ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+};
+
+struct SwitchIf
+{
+ enum
+ {
+ SWITCH,
+ IF
+ } type;
+ union
+ {
+ Cases * cases;
+ If * ifs;
+ } info;
+ SwitchIf (const Span * sp, uint32_t nsp, const State * next);
+ ~SwitchIf ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+};
+
+struct GoBitmap
+{
+ const BitMap * bitmap;
+ const State * bitmap_state;
+ SwitchIf * hgo;
+ SwitchIf * lgo;
+ GoBitmap (const Span * span, uint32_t nSpans, const Span * hspan, uint32_t hSpans, const BitMap * bm, const State * bm_state, const State * next);
+ ~GoBitmap ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+
+ FORBID_COPY (GoBitmap);
+};
+
+struct CpgotoTable
+{
+ static const uint32_t TABLE_SIZE;
+ const State ** table;
+ CpgotoTable (const Span * span, uint32_t nSpans);
+ ~CpgotoTable ();
+ void emit (OutputFile & o, uint32_t ind);
+ void used_labels (std::set & used);
+
+private:
+ label_t max_label () const;
+
+ FORBID_COPY (CpgotoTable);
+};
+
+struct Cpgoto
+{
+ SwitchIf * hgo;
+ CpgotoTable * table;
+ Cpgoto (const Span * span, uint32_t nSpans, const Span * hspan, uint32_t hSpans, const State * next);
+ ~Cpgoto ();
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+
+ FORBID_COPY (Cpgoto);
+};
+
+struct Dot
+{
+ const State * from;
+ Cases * cases;
+ Dot (const Span * sp, uint32_t nsp, const State * from);
+ ~Dot ();
+ void emit (OutputFile & o);
+
+ FORBID_COPY (Dot);
+};
+
+struct Go
+{
+ uint32_t nSpans; // number of spans
+ Span * span;
+ enum
+ {
+ EMPTY,
+ SWITCH_IF,
+ BITMAP,
+ CPGOTO,
+ DOT
+ } type;
+ union
+ {
+ SwitchIf * switchif;
+ GoBitmap * bitmap;
+ Cpgoto * cpgoto;
+ Dot * dot;
+ } info;
+
+ Go ();
+ ~Go ();
+ void init (const State * from);
+ void emit (OutputFile & o, uint32_t ind, bool & readCh);
+ void used_labels (std::set & used);
+
+ Go (const Go & g)
+ : nSpans (g.nSpans)
+ , span (g.span)
+ , type (g.type)
+ , info (g.info)
+ {}
+ Go & operator = (const Go & g)
+ {
+ nSpans = g.nSpans;
+ span = g.span;
+ type = g.type;
+ info = g.info;
+ return * this;
+ }
+};
+
+} // namespace re2c
+
+#endif // _RE2C_CODEGEN_GO_
diff --git a/tools/re2c/src/codegen/go_construct.cc b/tools/re2c/src/codegen/go_construct.cc
new file mode 100644
index 000000000..e680475f0
--- /dev/null
+++ b/tools/re2c/src/codegen/go_construct.cc
@@ -0,0 +1,284 @@
+#include
+#include "src/util/c99_stdint.h"
+#include
+#include
+#include
+
+#include "src/codegen/bitmap.h"
+#include "src/codegen/go.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+#include "src/ir/adfa/adfa.h"
+#include "src/util/allocate.h"
+
+namespace re2c
+{
+
+static uint32_t unmap (Span * new_span, const Span * old_span, uint32_t old_nspans, const State * x);
+
+Cases::Cases (const Span * span, uint32_t span_size)
+ : def (span_size == 0 ? NULL : span[span_size - 1].to)
+ , cases (new Case[span_size])
+ , cases_size (0)
+{
+ for (uint32_t i = 0, lb = 0; i < span_size; ++ i)
+ {
+ add (lb, span[i].ub, span[i].to);
+ lb = span[i].ub;
+ }
+}
+
+void Cases::add (uint32_t lb, uint32_t ub, State * to)
+{
+ for (uint32_t i = 0; i < cases_size; ++i)
+ {
+ if (cases[i].to == to)
+ {
+ cases[i].ranges.push_back (std::make_pair (lb, ub));
+ return;
+ }
+ }
+ cases[cases_size].ranges.push_back (std::make_pair (lb, ub));
+ cases[cases_size].to = to;
+ ++cases_size;
+}
+
+Cond::Cond (const std::string & cmp, uint32_t val)
+ : compare (cmp)
+ , value (val)
+{}
+
+Binary::Binary (const Span * s, uint32_t n, const State * next)
+ : cond (NULL)
+ , thn (NULL)
+ , els (NULL)
+{
+ const uint32_t l = n / 2;
+ const uint32_t h = n - l;
+ cond = new Cond ("<=", s[l - 1].ub - 1);
+ thn = new If (l > 4 ? If::BINARY : If::LINEAR, &s[0], l, next);
+ els = new If (h > 4 ? If::BINARY : If::LINEAR, &s[l], h, next);
+}
+
+Linear::Linear (const Span * s, uint32_t n, const State * next)
+ : branches ()
+{
+ for (;;)
+ {
+ const 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)
+ {
+ branches.push_back (std::make_pair (new Cond ("!=", s[0].ub), bg));
+ return ;
+ }
+ else
+ {
+ branches.push_back (std::make_pair (new Cond ("==", s[0].ub), s[1].to));
+ }
+ n -= 2;
+ s += 2;
+ }
+ if (n == 1)
+ {
+ if (next == NULL || s[0].to != next)
+ {
+ branches.push_back (std::make_pair (static_cast (NULL), s[0].to));
+ }
+ return;
+ }
+ else if (n == 2 && bg == next)
+ {
+ branches.push_back (std::make_pair (new Cond (">=", s[0].ub), s[1].to));
+ return;
+ }
+ else
+ {
+ branches.push_back (std::make_pair (new Cond ("<=", s[0].ub - 1), bg));
+ n -= 1;
+ s += 1;
+ }
+ }
+}
+
+If::If (type_t t, const Span * sp, uint32_t nsp, const State * next)
+ : type (t)
+ , info ()
+{
+ switch (type)
+ {
+ case BINARY:
+ info.binary = new Binary (sp, nsp, next);
+ break;
+ case LINEAR:
+ info.linear = new Linear (sp, nsp, next);
+ break;
+ }
+}
+
+SwitchIf::SwitchIf (const Span * sp, uint32_t nsp, const State * next)
+ : type (IF)
+ , info ()
+{
+ if ((!opts->sFlag && nsp > 2) || (nsp > 8 && (sp[nsp - 2].ub - sp[0].ub <= 3 * (nsp - 2))))
+ {
+ type = SWITCH;
+ info.cases = new Cases (sp, nsp);
+ }
+ else if (nsp > 5)
+ {
+ info.ifs = new If (If::BINARY, sp, nsp, next);
+ }
+ else
+ {
+ info.ifs = new If (If::LINEAR, sp, nsp, next);
+ }
+}
+
+GoBitmap::GoBitmap (const Span * span, uint32_t nSpans, const Span * hspan, uint32_t hSpans, const BitMap * bm, const State * bm_state, const State * next)
+ : bitmap (bm)
+ , bitmap_state (bm_state)
+ , hgo (NULL)
+ , lgo (NULL)
+{
+ Span * bspan = allocate (nSpans);
+ uint32_t bSpans = unmap (bspan, span, nSpans, bm_state);
+ lgo = bSpans == 0
+ ? NULL
+ : new SwitchIf (bspan, bSpans, next);
+ // if there are any low spans, then next state for high spans
+ // must be NULL to trigger explicit goto generation in linear 'if'
+ hgo = hSpans == 0
+ ? NULL
+ : new SwitchIf (hspan, hSpans, lgo ? NULL : next);
+ operator delete (bspan);
+}
+
+const uint32_t CpgotoTable::TABLE_SIZE = 0x100;
+
+CpgotoTable::CpgotoTable (const Span * span, uint32_t nSpans)
+ : table (new const State * [TABLE_SIZE])
+{
+ uint32_t c = 0;
+ for (uint32_t i = 0; i < nSpans; ++i)
+ {
+ for(; c < span[i].ub && c < TABLE_SIZE; ++c)
+ {
+ table[c] = span[i].to;
+ }
+ }
+}
+
+Cpgoto::Cpgoto (const Span * span, uint32_t nSpans, const Span * hspan, uint32_t hSpans, const State * next)
+ : hgo (hSpans == 0 ? NULL : new SwitchIf (hspan, hSpans, next))
+ , table (new CpgotoTable (span, nSpans))
+{}
+
+Dot::Dot (const Span * sp, uint32_t nsp, const State * s)
+ : from (s)
+ , cases (new Cases (sp, nsp))
+{}
+
+Go::Go ()
+ : nSpans (0)
+ , span (NULL)
+ , type (EMPTY)
+ , info ()
+{}
+
+void Go::init (const State * from)
+{
+ if (nSpans == 0)
+ {
+ return;
+ }
+
+ // initialize high (wide) spans
+ uint32_t hSpans = 0;
+ const Span * hspan = NULL;
+ for (uint32_t i = 0; i < nSpans; ++i)
+ {
+ if (span[i].ub > 0x100)
+ {
+ hspan = &span[i];
+ hSpans = nSpans - i;
+ break;
+ }
+ }
+
+ // initialize bitmaps
+ uint32_t nBitmaps = 0;
+ const BitMap * bitmap = NULL;
+ const State * bitmap_state = NULL;
+ for (uint32_t i = 0; i < nSpans; ++i)
+ {
+ if (span[i].to->isBase)
+ {
+ const BitMap *b = BitMap::find (span[i].to);
+ if (b && matches(b->go->span, b->go->nSpans, b->on, span, nSpans, span[i].to))
+ {
+ if (bitmap == NULL)
+ {
+ bitmap = b;
+ bitmap_state = span[i].to;
+ }
+ nBitmaps++;
+ }
+ }
+ }
+
+ const uint32_t dSpans = nSpans - hSpans - nBitmaps;
+ if (opts->target == opt_t::DOT)
+ {
+ type = DOT;
+ info.dot = new Dot (span, nSpans, from);
+ }
+ else if (opts->gFlag && (dSpans >= opts->cGotoThreshold))
+ {
+ type = CPGOTO;
+ info.cpgoto = new Cpgoto (span, nSpans, hspan, hSpans, from->next);
+ }
+ else if (opts->bFlag && (nBitmaps > 0))
+ {
+ type = BITMAP;
+ info.bitmap = new GoBitmap (span, nSpans, hspan, hSpans, bitmap, bitmap_state, from->next);
+ bUsedYYBitmap = true;
+ }
+ else
+ {
+ type = SWITCH_IF;
+ info.switchif = new SwitchIf (span, nSpans, from->next);
+ }
+}
+
+/*
+ * Find all spans, that map to the given state. For each of them,
+ * find upper adjacent span, that maps to another state (if such
+ * span exists, otherwize try lower one).
+ * If input contains single span that maps to the given state,
+ * then output contains 0 spans.
+ */
+uint32_t unmap (Span * new_span, const Span * old_span, uint32_t old_nspans, const State * x)
+{
+ uint32_t new_nspans = 0;
+ for (uint32_t i = 0; i < old_nspans; ++i)
+ {
+ if (old_span[i].to != x)
+ {
+ if (new_nspans > 0 && new_span[new_nspans - 1].to == old_span[i].to)
+ new_span[new_nspans - 1].ub = old_span[i].ub;
+ else
+ {
+ new_span[new_nspans].to = old_span[i].to;
+ new_span[new_nspans].ub = old_span[i].ub;
+ ++new_nspans;
+ }
+ }
+ }
+ if (new_nspans > 0)
+ new_span[new_nspans - 1].ub = old_span[old_nspans - 1].ub;
+ return new_nspans;
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/go_destruct.cc b/tools/re2c/src/codegen/go_destruct.cc
new file mode 100644
index 000000000..0160d48f7
--- /dev/null
+++ b/tools/re2c/src/codegen/go_destruct.cc
@@ -0,0 +1,99 @@
+#include "src/util/c99_stdint.h"
+#include
+#include
+
+#include "src/codegen/go.h"
+
+namespace re2c
+{
+
+Cases::~Cases ()
+{
+ delete [] cases;
+}
+
+Binary::~Binary ()
+{
+ delete cond;
+ delete thn;
+ delete els;
+}
+
+Linear::~Linear ()
+{
+ for (uint32_t i = 0; i < branches.size (); ++i)
+ {
+ delete branches[i].first;
+ }
+}
+
+If::~If ()
+{
+ switch (type)
+ {
+ case BINARY:
+ delete info.binary;
+ break;
+ case LINEAR:
+ delete info.linear;
+ break;
+ }
+}
+
+SwitchIf::~SwitchIf ()
+{
+ switch (type)
+ {
+ case SWITCH:
+ delete info.cases;
+ break;
+ case IF:
+ delete info.ifs;
+ break;
+ }
+}
+
+GoBitmap::~GoBitmap ()
+{
+ delete hgo;
+ delete lgo;
+}
+
+CpgotoTable::~CpgotoTable ()
+{
+ delete [] table;
+}
+
+Cpgoto::~Cpgoto ()
+{
+ delete hgo;
+ delete table;
+}
+
+Dot::~Dot ()
+{
+ delete cases;
+}
+
+Go::~Go ()
+{
+ switch (type)
+ {
+ case EMPTY:
+ break;
+ case SWITCH_IF:
+ delete info.switchif;
+ break;
+ case BITMAP:
+ delete info.bitmap;
+ break;
+ case CPGOTO:
+ delete info.cpgoto;
+ break;
+ case DOT:
+ delete info.dot;
+ break;
+ }
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/go_emit.cc b/tools/re2c/src/codegen/go_emit.cc
new file mode 100644
index 000000000..e970eee56
--- /dev/null
+++ b/tools/re2c/src/codegen/go_emit.cc
@@ -0,0 +1,271 @@
+#include
+#include "src/util/c99_stdint.h"
+#include
+#include
+#include
+
+#include "src/codegen/bitmap.h"
+#include "src/codegen/go.h"
+#include "src/codegen/input_api.h"
+#include "src/codegen/label.h"
+#include "src/codegen/output.h"
+#include "src/codegen/print.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+#include "src/ir/adfa/adfa.h"
+#include "src/ir/regexp/encoding/enc.h"
+
+namespace re2c
+{
+
+static void output_if (OutputFile & o, uint32_t ind, bool & readCh, const std::string & compare, uint32_t value);
+static void output_goto (OutputFile & o, uint32_t ind, bool & readCh, label_t to);
+static std::string output_yych (bool & readCh);
+static std::string output_hgo (OutputFile & o, uint32_t ind, bool & readCh, SwitchIf * hgo);
+
+std::string output_yych (bool & readCh)
+{
+ if (readCh)
+ {
+ readCh = false;
+ return "(" + opts->input_api.expr_peek_save () + ")";
+ }
+ else
+ {
+ return opts->yych;
+ }
+}
+
+void output_if (OutputFile & o, uint32_t ind, bool & readCh, const std::string & compare, uint32_t value)
+{
+ o.wind(ind).ws("if (").wstring(output_yych (readCh)).ws(" ").wstring(compare).ws(" ").wc_hex (value).ws(") ");
+}
+
+void output_goto (OutputFile & o, uint32_t ind, bool & readCh, label_t to)
+{
+ if (readCh)
+ {
+ o.wstring(opts->input_api.stmt_peek (ind));
+ readCh = false;
+ }
+ o.wind(ind).ws("goto ").wstring(opts->labelPrefix).wlabel(to).ws(";\n");
+}
+
+std::string output_hgo (OutputFile & o, uint32_t ind, bool & readCh, SwitchIf * hgo)
+{
+ std::string yych = output_yych (readCh);
+ if (hgo != NULL)
+ {
+ o.wind(ind).ws("if (").wstring(yych).ws(" & ~0xFF) {\n");
+ hgo->emit (o, ind + 1, readCh);
+ o.wind(ind).ws("} else ");
+ yych = opts->yych;
+ }
+ else
+ {
+ o.wind(ind);
+ }
+ return yych;
+}
+
+void Case::emit (OutputFile & o, uint32_t ind)
+{
+ for (uint32_t i = 0; i < ranges.size (); ++i)
+ {
+ for (uint32_t b = ranges[i].first; b < ranges[i].second; ++b)
+ {
+ o.wind(ind).ws("case ").wc_hex (b).ws(":");
+ if (opts->dFlag && opts->encoding.type () == Enc::EBCDIC)
+ {
+ const uint32_t c = opts->encoding.decodeUnsafe (b);
+ if (is_print (c))
+ o.ws(" /* ").wc(static_cast (c)).ws(" */");
+ }
+ bool last_case = i == ranges.size () - 1 && b == ranges[i].second - 1;
+ if (!last_case)
+ {
+ o.ws("\n");
+ }
+ }
+ }
+}
+
+void Cases::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ o.wind(ind).ws("switch (").wstring(output_yych (readCh)).ws(") {\n");
+ for (uint32_t i = 0; i < cases_size; ++i)
+ {
+ if (cases[i].to != def)
+ {
+ cases[i].emit (o, ind);
+ output_goto (o, 1, readCh, cases[i].to->label);
+ }
+ }
+ o.wind(ind).ws("default:");
+ output_goto (o, 1, readCh, def->label);
+ o.wind(ind).ws("}\n");
+}
+
+void Binary::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ output_if (o, ind, readCh, cond->compare, cond->value);
+ o.ws("{\n");
+ thn->emit (o, ind + 1, readCh);
+ o.wind(ind).ws("} else {\n");
+ els->emit (o, ind + 1, readCh);
+ o.wind(ind).ws("}\n");
+}
+
+void Linear::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ for (uint32_t i = 0; i < branches.size (); ++i)
+ {
+ if (branches[i].first != NULL)
+ {
+ output_if (o, ind, readCh, branches[i].first->compare, branches[i].first->value);
+ output_goto (o, 0, readCh, branches[i].second->label);
+ }
+ else
+ {
+ output_goto (o, ind, readCh, branches[i].second->label);
+ }
+ }
+}
+
+void If::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ switch (type)
+ {
+ case BINARY:
+ info.binary->emit (o, ind, readCh);
+ break;
+ case LINEAR:
+ info.linear->emit (o, ind, readCh);
+ break;
+ }
+}
+
+void SwitchIf::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ switch (type)
+ {
+ case SWITCH:
+ info.cases->emit (o, ind, readCh);
+ break;
+ case IF:
+ info.ifs->emit (o, ind, readCh);
+ break;
+ }
+}
+
+void GoBitmap::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ std::string yych = output_hgo (o, ind, readCh, hgo);
+ o.ws("if (").wstring(opts->yybm).ws("[").wu32(bitmap->i).ws("+").wstring(yych).ws("] & ");
+ if (opts->yybmHexTable)
+ {
+ o.wu32_hex(bitmap->m);
+ }
+ else
+ {
+ o.wu32(bitmap->m);
+ }
+ o.ws(") {\n");
+ output_goto (o, ind + 1, readCh, bitmap_state->label);
+ o.wind(ind).ws("}\n");
+ if (lgo != NULL)
+ {
+ lgo->emit (o, ind, readCh);
+ }
+}
+
+label_t CpgotoTable::max_label () const
+{
+ label_t max = label_t::first ();
+ for (uint32_t i = 0; i < TABLE_SIZE; ++i)
+ {
+ if (max < table[i]->label)
+ {
+ max = table[i]->label;
+ };
+ }
+ return max;
+}
+
+void CpgotoTable::emit (OutputFile & o, uint32_t ind)
+{
+ o.wind(ind).ws("static void *").wstring(opts->yytarget).ws("[256] = {\n");
+ o.wind(++ind);
+ const uint32_t max_digits = max_label ().width ();
+ for (uint32_t i = 0; i < TABLE_SIZE; ++i)
+ {
+ o.ws("&&").wstring(opts->labelPrefix).wlabel(table[i]->label);
+ if (i == TABLE_SIZE - 1)
+ {
+ o.ws("\n");
+ }
+ else if (i % 8 == 7)
+ {
+ o.ws(",\n").wind(ind);
+ }
+ else
+ {
+ const uint32_t padding = max_digits - table[i]->label.width () + 1;
+ o.ws(",").wstring(std::string (padding, ' '));
+ }
+ }
+ o.wind(--ind).ws("};\n");
+}
+
+void Cpgoto::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ std::string yych = output_hgo (o, ind, readCh, hgo);
+ o.ws("{\n");
+ table->emit (o, ++ind);
+ o.wind(ind).ws("goto *").wstring(opts->yytarget).ws("[").wstring(yych).ws("];\n");
+ o.wind(--ind).ws("}\n");
+}
+
+void Dot::emit (OutputFile & o)
+{
+ const uint32_t n = cases->cases_size;
+ if (n == 1)
+ {
+ o.wlabel(from->label).ws(" -> ").wlabel(cases->cases[0].to->label).ws("\n");
+ }
+ else
+ {
+ for (uint32_t i = 0; i < n; ++i)
+ {
+ o.wlabel(from->label).ws(" -> ").wlabel(cases->cases[i].to->label).ws(" [label=\"");
+ for (uint32_t j = 0; j < cases->cases[i].ranges.size (); ++j)
+ {
+ o.wrange(cases->cases[i].ranges[j].first, cases->cases[i].ranges[j].second);
+ }
+ o.ws("\"]\n");
+ }
+ }
+}
+
+void Go::emit (OutputFile & o, uint32_t ind, bool & readCh)
+{
+ switch (type)
+ {
+ case EMPTY:
+ break;
+ case SWITCH_IF:
+ info.switchif->emit (o, ind, readCh);
+ break;
+ case BITMAP:
+ info.bitmap->emit (o, ind, readCh);
+ break;
+ case CPGOTO:
+ info.cpgoto->emit (o, ind, readCh);
+ break;
+ case DOT:
+ info.dot->emit (o);
+ break;
+ }
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/go_used_labels.cc b/tools/re2c/src/codegen/go_used_labels.cc
new file mode 100644
index 000000000..09cf98ea8
--- /dev/null
+++ b/tools/re2c/src/codegen/go_used_labels.cc
@@ -0,0 +1,111 @@
+#include
+#include "src/util/c99_stdint.h"
+#include
+#include
+#include
+
+#include "src/codegen/go.h"
+#include "src/codegen/label.h"
+#include "src/ir/adfa/adfa.h"
+
+namespace re2c
+{
+
+void Cases::used_labels (std::set & used)
+{
+ for (uint32_t i = 0; i < cases_size; ++i)
+ {
+ used.insert (cases[i].to->label);
+ }
+}
+
+void Binary::used_labels (std::set & used)
+{
+ thn->used_labels (used);
+ els->used_labels (used);
+}
+
+void Linear::used_labels (std::set & used)
+{
+ for (uint32_t i = 0; i < branches.size (); ++i)
+ {
+ used.insert (branches[i].second->label);
+ }
+}
+
+void If::used_labels (std::set & used)
+{
+ switch (type)
+ {
+ case BINARY:
+ info.binary->used_labels (used);
+ break;
+ case LINEAR:
+ info.linear->used_labels (used);
+ break;
+ }
+}
+
+void SwitchIf::used_labels (std::set & used)
+{
+ switch (type)
+ {
+ case SWITCH:
+ info.cases->used_labels (used);
+ break;
+ case IF:
+ info.ifs->used_labels (used);
+ break;
+ }
+}
+
+void GoBitmap::used_labels (std::set & used)
+{
+ if (hgo != NULL)
+ {
+ hgo->used_labels (used);
+ }
+ used.insert (bitmap_state->label);
+ if (lgo != NULL)
+ {
+ lgo->used_labels (used);
+ }
+}
+
+void CpgotoTable::used_labels (std::set & used)
+{
+ for (uint32_t i = 0; i < TABLE_SIZE; ++i)
+ {
+ used.insert (table[i]->label);
+ }
+}
+
+void Cpgoto::used_labels (std::set & used)
+{
+ if (hgo != NULL)
+ {
+ hgo->used_labels (used);
+ }
+ table->used_labels (used);
+}
+
+void Go::used_labels (std::set & used)
+{
+ switch (type)
+ {
+ case EMPTY:
+ case DOT:
+ break;
+ case SWITCH_IF:
+ info.switchif->used_labels (used);
+ break;
+ case BITMAP:
+ info.bitmap->used_labels (used);
+ break;
+ case CPGOTO:
+ info.cpgoto->used_labels (used);
+ break;
+ }
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/indent.h b/tools/re2c/src/codegen/indent.h
new file mode 100644
index 000000000..d2d8f369a
--- /dev/null
+++ b/tools/re2c/src/codegen/indent.h
@@ -0,0 +1,24 @@
+#ifndef _RE2C_CODEGEN_INDENT_
+#define _RE2C_CODEGEN_INDENT_
+
+#include
+
+#include "src/globals.h"
+
+namespace re2c
+{
+
+inline std::string indent (uint32_t ind)
+{
+ std::string str;
+
+ while (opts->target != opt_t::DOT && ind-- > 0)
+ {
+ str += opts->indString;
+ }
+ return str;
+}
+
+} // end namespace re2c
+
+#endif // _RE2C_CODEGEN_INDENT_
diff --git a/tools/re2c/src/codegen/input_api.cc b/tools/re2c/src/codegen/input_api.cc
new file mode 100644
index 000000000..f2e32c387
--- /dev/null
+++ b/tools/re2c/src/codegen/input_api.cc
@@ -0,0 +1,175 @@
+#include
+
+#include "src/codegen/input_api.h"
+#include "src/codegen/indent.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+
+namespace re2c
+{
+
+InputAPI::InputAPI ()
+ : type_ (DEFAULT)
+{}
+
+InputAPI::type_t InputAPI::type () const
+{
+ return type_;
+}
+
+void InputAPI::set (type_t t)
+{
+ type_ = t;
+}
+
+std::string InputAPI::expr_peek () const
+{
+ std::string s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s = "*" + opts->yycursor;
+ break;
+ case CUSTOM:
+ s = opts->yypeek + " ()";
+ break;
+ }
+ return s;
+}
+
+std::string InputAPI::expr_peek_save () const
+{
+ return opts->yych + " = " + opts.yychConversion () + expr_peek ();
+}
+
+std::string InputAPI::stmt_peek (uint32_t ind) const
+{
+ return indent (ind) + expr_peek_save () + ";\n";
+}
+
+std::string InputAPI::stmt_skip (uint32_t ind) const
+{
+ std::string s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s = "++" + opts->yycursor;
+ break;
+ case CUSTOM:
+ s = opts->yyskip + " ()";
+ break;
+ }
+ return indent (ind) + s + ";\n";
+}
+
+std::string InputAPI::stmt_backup (uint32_t ind) const
+{
+ std::string s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s = opts->yymarker + " = " + opts->yycursor;
+ break;
+ case CUSTOM:
+ s = opts->yybackup + " ()";
+ break;
+ }
+ return indent (ind) + s + ";\n";
+}
+
+std::string InputAPI::stmt_backupctx (uint32_t ind) const
+{
+ std::string s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s = opts->yyctxmarker + " = " + opts->yycursor;
+ break;
+ case CUSTOM:
+ s = opts->yybackupctx + " ()";
+ break;
+ }
+ return indent (ind) + s + ";\n";
+}
+
+std::string InputAPI::stmt_restore (uint32_t ind) const
+{
+ std::string s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s = opts->yycursor + " = " + opts->yymarker;
+ break;
+ case CUSTOM:
+ s = opts->yyrestore + " ()";
+ break;
+ }
+ return indent (ind) + s + ";\n";
+}
+
+std::string InputAPI::stmt_restorectx (uint32_t ind) const
+{
+ std::string s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s = indent (ind) + opts->yycursor + " = " + opts->yyctxmarker + ";\n";
+ break;
+ case CUSTOM:
+ s = indent (ind) + opts->yyrestorectx + " ();\n";
+ break;
+ }
+ return s;
+}
+
+std::string InputAPI::stmt_skip_peek (uint32_t ind) const
+{
+ return type_ == DEFAULT
+ ? indent (ind) + opts->yych + " = " + opts.yychConversion () + "*++" + opts->yycursor + ";\n"
+ : stmt_skip (ind) + stmt_peek (ind);
+}
+
+std::string InputAPI::stmt_skip_backup (uint32_t ind) const
+{
+ return type_ == DEFAULT
+ ? indent (ind) + opts->yymarker + " = ++" + opts->yycursor + ";\n"
+ : stmt_skip (ind) + stmt_backup (ind);
+}
+
+std::string InputAPI::stmt_backup_peek (uint32_t ind) const
+{
+ return type_ == DEFAULT
+ ? indent (ind) + opts->yych + " = " + opts.yychConversion () + "*(" + opts->yymarker + " = " + opts->yycursor + ");\n"
+ : stmt_backup (ind) + stmt_peek (ind);
+}
+
+std::string InputAPI::stmt_skip_backup_peek (uint32_t ind) const
+{
+ return type_ == DEFAULT
+ ? indent (ind) + opts->yych + " = " + opts.yychConversion () + "*(" + opts->yymarker + " = ++" + opts->yycursor + ");\n"
+ : stmt_skip (ind) + stmt_backup (ind) + stmt_peek (ind);
+}
+
+std::string InputAPI::expr_lessthan_one () const
+{
+ return type_ == DEFAULT
+ ? opts->yylimit + " <= " + opts->yycursor
+ : expr_lessthan (1);
+}
+
+std::string InputAPI::expr_lessthan (size_t n) const
+{
+ std::ostringstream s;
+ switch (type_)
+ {
+ case DEFAULT:
+ s << "(" << opts->yylimit << " - " << opts->yycursor << ") < " << n;
+ break;
+ case CUSTOM:
+ s << opts->yylessthan << " (" << n << ")";
+ break;
+ }
+ return s.str ();
+}
+
+} // end namespace re2c
diff --git a/tools/re2c/src/codegen/input_api.h b/tools/re2c/src/codegen/input_api.h
new file mode 100644
index 000000000..423475e6b
--- /dev/null
+++ b/tools/re2c/src/codegen/input_api.h
@@ -0,0 +1,43 @@
+#ifndef _RE2C_CODEGEN_INPUT_API_
+#define _RE2C_CODEGEN_INPUT_API_
+
+#include "src/util/c99_stdint.h"
+#include
+
+namespace re2c
+{
+
+class InputAPI
+{
+public:
+ enum type_t
+ { DEFAULT
+ , CUSTOM
+ };
+
+private:
+ type_t type_;
+
+public:
+ InputAPI ();
+ type_t type () const;
+ void set (type_t t);
+ std::string expr_peek () const;
+ std::string expr_peek_save () const;
+ std::string stmt_peek (uint32_t ind) const;
+ std::string stmt_skip (uint32_t ind) const;
+ std::string stmt_backup (uint32_t ind) const;
+ std::string stmt_backupctx (uint32_t ind) const;
+ std::string stmt_restore (uint32_t ind) const;
+ std::string stmt_restorectx (uint32_t ind) const;
+ std::string stmt_skip_peek (uint32_t ind) const;
+ std::string stmt_skip_backup (uint32_t ind) const;
+ std::string stmt_backup_peek (uint32_t ind) const;
+ std::string stmt_skip_backup_peek (uint32_t ind) const;
+ std::string expr_lessthan_one () const;
+ std::string expr_lessthan (size_t n) const;
+};
+
+} // end namespace re2c
+
+#endif // _RE2C_CODEGEN_INPUT_API_
diff --git a/tools/re2c/src/codegen/label.cc b/tools/re2c/src/codegen/label.cc
new file mode 100644
index 000000000..c2e384fbf
--- /dev/null
+++ b/tools/re2c/src/codegen/label.cc
@@ -0,0 +1,42 @@
+#include
+
+#include "src/codegen/label.h"
+
+namespace re2c {
+
+const uint32_t label_t::FIRST = 0;
+
+label_t::label_t ()
+ : value (FIRST)
+{}
+
+void label_t::inc ()
+{
+ ++value;
+}
+
+label_t label_t::first ()
+{
+ return label_t ();
+}
+
+bool label_t::operator < (const label_t & l) const
+{
+ return value < l.value;
+}
+
+uint32_t label_t::width () const
+{
+ uint32_t v = value;
+ uint32_t n = 0;
+ while (v /= 10) ++n;
+ return n;
+}
+
+std::ostream & operator << (std::ostream & o, label_t l)
+{
+ o << l.value;
+ return o;
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/label.h b/tools/re2c/src/codegen/label.h
new file mode 100644
index 000000000..cb2179d3c
--- /dev/null
+++ b/tools/re2c/src/codegen/label.h
@@ -0,0 +1,39 @@
+#ifndef _RE2C_CODEGEN_LABEL_
+#define _RE2C_CODEGEN_LABEL_
+
+#include // ostream
+
+#include "src/util/c99_stdint.h"
+
+namespace re2c {
+
+template class counter_t;
+
+// label public API:
+// - get first label
+// - compare labels
+// - get label width
+// - output label to std::ostream
+//
+// label private API (for label counter):
+// - get initial label
+// - get next label
+class label_t
+{
+ static const uint32_t FIRST;
+ uint32_t value;
+ label_t ();
+ void inc ();
+
+public:
+ static label_t first ();
+ bool operator < (const label_t & l) const;
+ uint32_t width () const;
+ friend std::ostream & operator << (std::ostream & o, label_t l);
+
+ friend class counter_t;
+};
+
+} // namespace re2c
+
+#endif // _RE2C_CODEGEN_LABEL_
diff --git a/tools/re2c/src/codegen/output.cc b/tools/re2c/src/codegen/output.cc
new file mode 100644
index 000000000..5276ef77e
--- /dev/null
+++ b/tools/re2c/src/codegen/output.cc
@@ -0,0 +1,465 @@
+#include
+#include
+#include
+
+#include "src/codegen/indent.h"
+#include "src/codegen/output.h"
+#include "src/codegen/print.h"
+#include "src/conf/opt.h"
+#include "src/conf/warn.h"
+#include "src/globals.h"
+#include "src/ir/rule_rank.h"
+
+namespace re2c
+{
+
+OutputFragment::OutputFragment (type_t t, uint32_t i)
+ : type (t)
+ , stream ()
+ , indent (i)
+{}
+
+uint32_t OutputFragment::count_lines ()
+{
+ uint32_t lines = 0;
+ const std::string content = stream.str ();
+ const char * p = content.c_str ();
+ for (uint32_t i = 0; i < content.size (); ++i)
+ {
+ if (p[i] == '\n')
+ {
+ ++lines;
+ }
+ }
+ return lines;
+}
+
+OutputBlock::OutputBlock ()
+ : fragments ()
+ , used_yyaccept (false)
+ , force_start_label (false)
+ , user_start_label ()
+ , line (0)
+{
+ fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
+}
+
+OutputBlock::~OutputBlock ()
+{
+ for (unsigned int i = 0; i < fragments.size (); ++i)
+ {
+ delete fragments[i];
+ }
+}
+
+OutputFile::OutputFile (const char * fn)
+ : file_name (fn)
+ , file (NULL)
+ , blocks ()
+ , label_counter ()
+ , warn_condition_order (!opts->tFlag) // see note [condition order]
+{
+ new_block ();
+}
+
+bool OutputFile::open ()
+{
+ if (file_name == NULL)
+ {
+ file_name = "";
+ file = stdout;
+ }
+ else
+ {
+ file = fopen (file_name, "wb");
+ }
+ return file != NULL;
+}
+
+OutputFile::~OutputFile ()
+{
+ if (file != NULL && file != stdout)
+ {
+ fclose (file);
+ }
+ for (unsigned int i = 0; i < blocks.size (); ++i)
+ {
+ delete blocks[i];
+ }
+}
+
+std::ostream & OutputFile::stream ()
+{
+ return blocks.back ()->fragments.back ()->stream;
+}
+
+OutputFile & OutputFile::wraw (const char * s, size_t n)
+{
+ stream ().write (s, static_cast (n));
+ return *this;
+}
+
+OutputFile & OutputFile::wu32_hex (uint32_t n)
+{
+ prtHex (stream (), n);
+ return *this;
+}
+
+OutputFile & OutputFile::wc_hex (uint32_t n)
+{
+ prtChOrHex (stream (), n);
+ return *this;
+}
+
+OutputFile & OutputFile::wrange (uint32_t l, uint32_t u)
+{
+ printSpan (stream (), l, u);
+ return *this;
+}
+
+OutputFile & OutputFile::wu32_width (uint32_t n, int w)
+{
+ stream () << std::setw (w);
+ stream () << n;
+ return *this;
+}
+
+OutputFile & OutputFile::wline_info (uint32_t l, const char * fn)
+{
+ output_line_info (stream (), l, fn);
+ return *this;
+}
+
+OutputFile & OutputFile::wversion_time ()
+{
+ output_version_time (stream ());
+ return *this;
+}
+
+OutputFile & OutputFile::wuser_start_label ()
+{
+ const std::string label = blocks.back ()->user_start_label;
+ if (!label.empty ())
+ {
+ wstring(label).ws(":\n");
+ }
+ return *this;
+}
+
+OutputFile & OutputFile::wc (char c)
+{
+ stream () << c;
+ return *this;
+}
+
+OutputFile & OutputFile::wu32 (uint32_t n)
+{
+ stream () << n;
+ return *this;
+}
+
+OutputFile & OutputFile::wu64 (uint64_t n)
+{
+ stream () << n;
+ return *this;
+}
+
+OutputFile & OutputFile::wstring (const std::string & s)
+{
+ stream () << s;
+ return *this;
+}
+
+OutputFile & OutputFile::ws (const char * s)
+{
+ stream () << s;
+ return *this;
+}
+
+OutputFile & OutputFile::wlabel (label_t l)
+{
+ stream () << l;
+ return *this;
+}
+
+OutputFile & OutputFile::wrank (rule_rank_t r)
+{
+ stream () << r;
+ return *this;
+}
+
+OutputFile & OutputFile::wind (uint32_t ind)
+{
+ stream () << indent(ind);
+ return *this;
+}
+
+void OutputFile::insert_code ()
+{
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
+}
+
+OutputFile & OutputFile::wdelay_line_info ()
+{
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::LINE_INFO, 0));
+ insert_code ();
+ return *this;
+}
+
+OutputFile & OutputFile::wdelay_state_goto (uint32_t ind)
+{
+ if (opts->fFlag && !bWroteGetState)
+ {
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::STATE_GOTO, ind));
+ insert_code ();
+ bWroteGetState = true;
+ }
+ return *this;
+}
+
+OutputFile & OutputFile::wdelay_types ()
+{
+ warn_condition_order = false; // see note [condition order]
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::TYPES, 0));
+ insert_code ();
+ return *this;
+}
+
+OutputFile & OutputFile::wdelay_warn_condition_order ()
+{
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::WARN_CONDITION_ORDER, 0));
+ insert_code ();
+ return *this;
+}
+
+OutputFile & OutputFile::wdelay_yyaccept_init (uint32_t ind)
+{
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::YYACCEPT_INIT, ind));
+ insert_code ();
+ return *this;
+}
+
+OutputFile & OutputFile::wdelay_yymaxfill ()
+{
+ blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::YYMAXFILL, 0));
+ insert_code ();
+ return *this;
+}
+
+void OutputFile::set_used_yyaccept ()
+{
+ blocks.back ()->used_yyaccept = true;
+}
+
+bool OutputFile::get_used_yyaccept () const
+{
+ return blocks.back ()->used_yyaccept;
+}
+
+void OutputFile::set_force_start_label (bool force)
+{
+ blocks.back ()->force_start_label = force;
+}
+
+void OutputFile::set_user_start_label (const std::string & label)
+{
+ blocks.back ()->user_start_label = label;
+}
+
+bool OutputFile::get_force_start_label () const
+{
+ return blocks.back ()->force_start_label;
+}
+
+void OutputFile::set_block_line (uint32_t l)
+{
+ blocks.back ()->line = l;
+}
+
+uint32_t OutputFile::get_block_line () const
+{
+ return blocks.back ()->line;
+}
+
+void OutputFile::new_block ()
+{
+ blocks.push_back (new OutputBlock ());
+ insert_code ();
+}
+
+void OutputFile::emit
+ ( const std::vector & types
+ , size_t max_fill
+ )
+{
+ if (file != NULL)
+ {
+ unsigned int line_count = 1;
+ for (unsigned int j = 0; j < blocks.size (); ++j)
+ {
+ OutputBlock & b = * blocks[j];
+ for (unsigned int i = 0; i < b.fragments.size (); ++i)
+ {
+ OutputFragment & f = * b.fragments[i];
+ switch (f.type)
+ {
+ case OutputFragment::CODE:
+ break;
+ case OutputFragment::LINE_INFO:
+ output_line_info (f.stream, line_count + 1, file_name);
+ break;
+ case OutputFragment::STATE_GOTO:
+ output_state_goto (f.stream, f.indent, 0);
+ break;
+ case OutputFragment::TYPES:
+ output_types (f.stream, f.indent, types);
+ break;
+ case OutputFragment::WARN_CONDITION_ORDER:
+ if (warn_condition_order) // see note [condition order]
+ {
+ warn.condition_order (b.line);
+ }
+ break;
+ case OutputFragment::YYACCEPT_INIT:
+ output_yyaccept_init (f.stream, f.indent, b.used_yyaccept);
+ break;
+ case OutputFragment::YYMAXFILL:
+ output_yymaxfill (f.stream, max_fill);
+ break;
+ }
+ std::string content = f.stream.str ();
+ fwrite (content.c_str (), 1, content.size (), file);
+ line_count += f.count_lines ();
+ }
+ }
+ }
+}
+
+HeaderFile::HeaderFile (const char * fn)
+ : stream ()
+ // header is always generated, but not always dumped to file
+ // NULL filename crashes 'operator <<' on some platforms
+ // TODO: generate header only if necessary
+ , file_name (fn ? fn : ".h")
+ , file (NULL)
+{}
+
+bool HeaderFile::open ()
+{
+ file = fopen (file_name, "wb");
+ return file != NULL;
+}
+
+void HeaderFile::emit (const std::vector & types)
+{
+ output_version_time (stream);
+ output_line_info (stream, 3, file_name);
+ stream << "\n";
+ output_types (stream, 0, types);
+}
+
+HeaderFile::~HeaderFile ()
+{
+ if (file != NULL)
+ {
+ std::string content = stream.str ();
+ fwrite (content.c_str (), 1, content.size (), file);
+ fclose (file);
+ }
+}
+
+Output::Output (const char * source_name, const char * header_name)
+ : source (source_name)
+ , header (header_name)
+ , types ()
+ , skeletons ()
+ , max_fill (1)
+{}
+
+Output::~Output ()
+{
+ if (!warn.error ())
+ {
+ source.emit (types, max_fill);
+ header.emit (types);
+ }
+}
+
+void output_state_goto (std::ostream & o, uint32_t ind, uint32_t start_label)
+{
+ o << indent(ind) << "switch (" << output_get_state() << ") {\n";
+ if (opts->bUseStateAbort)
+ {
+ o << indent(ind) << "default: abort();\n";
+ o << indent(ind) << "case -1: goto " << opts->labelPrefix << start_label << ";\n";
+ }
+ else
+ {
+ o << indent(ind) << "default: goto " << opts->labelPrefix << start_label << ";\n";
+ }
+ for (uint32_t i = 0; i < last_fill_index; ++i)
+ {
+ o << indent(ind) << "case " << i << ": goto " << opts->yyfilllabel << i << ";\n";
+ }
+ o << indent(ind) << "}\n";
+ if (opts->bUseStateNext)
+ {
+ o << opts->yynext << ":\n";
+ }
+}
+
+void output_yyaccept_init (std::ostream & o, uint32_t ind, bool used_yyaccept)
+{
+ if (used_yyaccept)
+ {
+ o << indent (ind) << "unsigned int " << opts->yyaccept << " = 0;\n";
+ }
+}
+
+void output_yymaxfill (std::ostream & o, size_t max_fill)
+{
+ o << "#define YYMAXFILL " << max_fill << "\n";
+}
+
+void output_line_info (std::ostream & o, uint32_t line_number, const char * file_name)
+{
+ if (!opts->iFlag)
+ {
+ o << "#line " << line_number << " \"" << file_name << "\"\n";
+ }
+}
+
+void output_types (std::ostream & o, uint32_t ind, const std::vector & types)
+{
+ o << indent (ind++) << "enum " << opts->yycondtype << " {\n";
+ for (unsigned int i = 0; i < types.size (); ++i)
+ {
+ o << indent (ind) << opts->condEnumPrefix << types[i] << ",\n";
+ }
+ o << indent (--ind) << "};\n";
+}
+
+void output_version_time (std::ostream & o)
+{
+ o << "/* Generated by re2c";
+ if (opts->version)
+ {
+ o << " " << PACKAGE_VERSION;
+ }
+ if (!opts->bNoGenerationDate)
+ {
+ o << " on ";
+ time_t now = time (NULL);
+ o.write (ctime (&now), 24);
+ }
+ o << " */" << "\n";
+}
+
+std::string output_get_state ()
+{
+ return opts->state_get_naked
+ ? opts->state_get
+ : opts->state_get + "()";
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/codegen/output.h b/tools/re2c/src/codegen/output.h
new file mode 100644
index 000000000..774fea352
--- /dev/null
+++ b/tools/re2c/src/codegen/output.h
@@ -0,0 +1,158 @@
+#ifndef _RE2C_CODEGEN_OUTPUT_
+#define _RE2C_CODEGEN_OUTPUT_
+
+#include "src/util/c99_stdint.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "src/codegen/label.h"
+#include "src/util/counter.h"
+#include "src/util/forbid_copy.h"
+
+namespace re2c
+{
+
+class rule_rank_t;
+
+struct OutputFragment
+{
+ enum type_t
+ { CODE
+// , CONFIG
+ , LINE_INFO
+ , STATE_GOTO
+ , TYPES
+ , WARN_CONDITION_ORDER
+ , YYACCEPT_INIT
+ , YYMAXFILL
+ };
+
+ type_t type;
+ std::ostringstream stream;
+ uint32_t indent;
+
+ OutputFragment (type_t t, uint32_t i);
+ uint32_t count_lines ();
+};
+
+struct OutputBlock
+{
+ std::vector fragments;
+ bool used_yyaccept;
+ bool force_start_label;
+ std::string user_start_label;
+ uint32_t line;
+
+ OutputBlock ();
+ ~OutputBlock ();
+};
+
+struct OutputFile
+{
+public:
+ const char * file_name;
+
+private:
+ FILE * file;
+ std::vector blocks;
+
+public:
+ counter_t label_counter;
+ bool warn_condition_order;
+
+private:
+ std::ostream & stream ();
+ void insert_code ();
+
+public:
+ OutputFile (const char * fn);
+ ~OutputFile ();
+
+ bool open ();
+
+ void new_block ();
+
+ // immediate output
+ OutputFile & wraw (const char * s, size_t n);
+ OutputFile & wc (char c);
+ OutputFile & wc_hex (uint32_t n);
+ OutputFile & wu32 (uint32_t n);
+ OutputFile & wu32_hex (uint32_t n);
+ OutputFile & wu32_width (uint32_t n, int w);
+ OutputFile & wu64 (uint64_t n);
+ OutputFile & wstring (const std::string & s);
+ OutputFile & ws (const char * s);
+ OutputFile & wlabel (label_t l);
+ OutputFile & wrank (rule_rank_t l);
+ OutputFile & wrange (uint32_t u, uint32_t l);
+ OutputFile & wline_info (uint32_t l, const char * fn);
+ OutputFile & wversion_time ();
+ OutputFile & wuser_start_label ();
+ OutputFile & wind (uint32_t ind);
+
+ // delayed output
+ OutputFile & wdelay_line_info ();
+ OutputFile & wdelay_state_goto (uint32_t ind);
+ OutputFile & wdelay_types ();
+ OutputFile & wdelay_warn_condition_order ();
+ OutputFile & wdelay_yyaccept_init (uint32_t ind);
+ OutputFile & wdelay_yymaxfill ();
+
+ void set_used_yyaccept ();
+ bool get_used_yyaccept () const;
+ void set_force_start_label (bool force);
+ void set_user_start_label (const std::string & label);
+ bool get_force_start_label () const;
+ void set_block_line (uint32_t l);
+ uint32_t get_block_line () const;
+
+ void emit (const std::vector & types, size_t max_fill);
+
+ FORBID_COPY (OutputFile);
+};
+
+struct HeaderFile
+{
+ HeaderFile (const char * fn);
+ ~HeaderFile ();
+ bool open ();
+ void emit (const std::vector & types);
+
+private:
+ std::ostringstream stream;
+ const char * file_name;
+ FILE * file;
+
+ FORBID_COPY (HeaderFile);
+};
+
+struct Output
+{
+ OutputFile source;
+ HeaderFile header;
+ std::vector types;
+ std::set skeletons;
+ size_t max_fill;
+
+ Output (const char * source_name, const char * header_name);
+ ~Output ();
+};
+
+void output_line_info (std::ostream &, uint32_t, const char *);
+void output_state_goto (std::ostream &, uint32_t, uint32_t);
+void output_types (std::ostream &, uint32_t, const std::vector &);
+void output_version_time (std::ostream &);
+void output_yyaccept_init (std::ostream &, uint32_t, bool);
+void output_yymaxfill (std::ostream &, size_t);
+
+// helpers
+std::string output_get_state ();
+
+} // namespace re2c
+
+#endif // _RE2C_CODEGEN_OUTPUT_
diff --git a/tools/re2c/src/codegen/print.cc b/tools/re2c/src/codegen/print.cc
new file mode 100644
index 000000000..2303e847f
--- /dev/null
+++ b/tools/re2c/src/codegen/print.cc
@@ -0,0 +1,156 @@
+#include
+
+#include "src/codegen/print.h"
+#include "src/conf/opt.h"
+#include "src/globals.h"
+#include "src/ir/regexp/encoding/enc.h"
+
+namespace re2c
+{
+
+bool is_print (uint32_t c)
+{
+ return c >= 0x20 && c < 0x7F;
+}
+
+bool is_space (uint32_t c)
+{
+ switch (c)
+ {
+ case '\t':
+ case '\f':
+ case '\v':
+ case '\n':
+ case '\r':
+ case ' ':
+ return true;
+ default:
+ return false;
+ }
+}
+
+char hexCh(uint32_t c)
+{
+ static const char * sHex = "0123456789ABCDEF";
+ return sHex[c & 0x0F];
+}
+
+void prtChOrHex(std::ostream& o, uint32_t c)
+{
+ if (opts->encoding.type () != Enc::EBCDIC
+ && (is_print (c) || is_space (c)))
+ {
+ o << '\'';
+ prtCh(o, c);
+ o << '\'';
+ }
+ else
+ {
+ prtHex(o, c);
+ }
+}
+
+void prtHex(std::ostream& o, uint32_t c)
+{
+ o << "0x";
+ const uint32_t cunit_size = opts->encoding.szCodeUnit ();
+ if (cunit_size >= 4)
+ {
+ o << hexCh (c >> 28u)
+ << hexCh (c >> 24u)
+ << hexCh (c >> 20u)
+ << hexCh (c >> 16u);
+ }
+ if (cunit_size >= 2)
+ {
+ o << hexCh (c >> 12u)
+ << hexCh (c >> 8u);
+ }
+ o << hexCh (c >> 4u)
+ << hexCh (c);
+}
+
+void prtCh(std::ostream& o, uint32_t c)
+{
+ const bool dot = opts->target == opt_t::DOT;
+
+ switch (c)
+ {
+ case '\'':
+ o << (dot ? "'" : "\\'");
+ break;
+
+ case '"':
+ o << (dot ? "\\\"" : "\"");
+ break;
+
+ case '\n':
+ o << (dot ? "\\\\n" : "\\n");
+ break;
+
+ case '\t':
+ o << (dot ? "\\\\t" : "\\t");
+ break;
+
+ case '\v':
+ o << (dot ? "\\\\v" : "\\v");
+ break;
+
+ case '\b':
+ o << (dot ? "\\\\b" : "\\b");
+ break;
+
+ case '\r':
+ o << (dot ? "\\\\r" : "\\r");
+ break;
+
+ case '\f':
+ o << (dot ? "\\\\f" : "\\f");
+ break;
+
+ case '\a':
+ o << (dot ? "\\\\a" :"\\a");
+ break;
+
+ case '\\':
+ o << "\\\\"; // both .dot and C/C++ code expect "\\"
+ break;
+
+ default:
+ o << static_cast (c);
+ break;
+ }
+}
+
+void prtChOrHexForSpan(std::ostream& o, uint32_t c)
+{
+ if (opts->encoding.type () != Enc::EBCDIC
+ && is_print (c)
+ && (c != ']'))
+ {
+ prtCh(o, c);
+ }
+ else
+ {
+ prtHex(o, c);
+ }
+}
+
+void printSpan(std::ostream& o, uint32_t lb, uint32_t ub)
+{
+ o << "[";
+ if ((ub - lb) == 1)
+ {
+ prtChOrHexForSpan(o, lb);
+ }
+ else
+ {
+ prtChOrHexForSpan(o, lb);
+ o << "-";
+ prtChOrHexForSpan(o, ub - 1);
+ }
+ o << "]";
+}
+
+} // end namespace re2c
+
diff --git a/tools/re2c/src/codegen/print.h b/tools/re2c/src/codegen/print.h
new file mode 100644
index 000000000..978d13e5c
--- /dev/null
+++ b/tools/re2c/src/codegen/print.h
@@ -0,0 +1,20 @@
+#ifndef _RE2C_CODEGEN_PRINT_
+#define _RE2C_CODEGEN_PRINT_
+
+#include "src/util/c99_stdint.h"
+#include
+
+namespace re2c
+{
+
+bool is_print (uint32_t c);
+bool is_space (uint32_t c);
+char hexCh(uint32_t c);
+void prtCh(std::ostream&, uint32_t);
+void prtHex(std::ostream&, uint32_t);
+void prtChOrHex(std::ostream&, uint32_t);
+void printSpan(std::ostream&, uint32_t, uint32_t);
+
+} // end namespace re2c
+
+#endif // _RE2C_CODEGEN_PRINT_
diff --git a/tools/re2c/src/conf/msg.cc b/tools/re2c/src/conf/msg.cc
new file mode 100644
index 000000000..87962f0a9
--- /dev/null
+++ b/tools/re2c/src/conf/msg.cc
@@ -0,0 +1,258 @@
+#include
+#include
+#include
+
+#if defined(_MSC_VER) && _MSC_VER < 1500
+#include "config.msc.h"
+#else
+#include "config.h"
+#endif
+#include "src/conf/msg.h"
+
+namespace re2c {
+
+void error (const char * fmt, ...)
+{
+ fprintf (stderr, "re2c: error: ");
+
+ va_list args;
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+
+ fprintf (stderr, "\n");
+}
+
+void error_encoding ()
+{
+ error ("only one of switches -e, -w, -x, -u and -8 must be set");
+}
+
+void error_arg (const char * option)
+{
+ error ("expected argument to option %s", option);
+}
+
+void warning_start (uint32_t line, bool error)
+{
+ static const char * msg = error ? "error" : "warning";
+ fprintf (stderr, "re2c: %s: line %u: ", msg, line);
+}
+
+void warning_end (const char * type, bool error)
+{
+ if (type != NULL)
+ {
+ const char * prefix = error ? "error-" : "";
+ fprintf (stderr, " [-W%s%s]", prefix, type);
+ }
+ fprintf (stderr, "\n");
+}
+
+void warning (const char * type, uint32_t line, bool error, const char * fmt, ...)
+{
+ warning_start (line, error);
+
+ va_list args;
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+
+ warning_end (type, error);
+}
+
+void usage ()
+{
+ fprintf (stderr,
+ "usage: re2c [-bcdDefFghirsuvVwx18] [-o of] [-t th] file\n"
+ "\n"
+ "-? -h --help Display this info.\n"
+ "\n"
+ "-b --bit-vectors Implies -s. Use bit vectors as well in the attempt to\n"
+ " coax better code out of the compiler. Most useful for\n"
+ " specifications with more than a few keywords (e.g. for\n"
+ " most programming languages).\n"
+ "\n"
+ "-c --conditions Require start conditions.\n"
+ "\n"
+ "-d --debug-output Creates a parser that dumps information during\n"
+ " about the current position and in which state the\n"
+ " parser is.\n"
+ "\n"
+ "-D --emit-dot Emit a Graphviz dot view of the DFA graph\n"
+ "\n"
+ "-e --ecb Generate a parser that supports EBCDIC. The generated code\n"
+ " can deal with any character up to 0xFF. In this mode re2c\n"
+ " assumes that input character size is 1 byte. This switch is\n"
+ " incompatible with -w, -u, -x and -8\n"
+ "\n"
+ "-f --storable-state Generate a scanner that supports storable states.\n"
+ "\n"
+ "-F --flex-syntax Partial support for flex syntax.\n"
+ "\n"
+ "-g --computed-gotos Implies -b. Generate computed goto code (only useable\n"
+ " with gcc).\n"
+ "\n"
+ "-i --no-debug-info Do not generate '#line' info (useful for versioning).\n"
+ "\n"
+ "-o of --output=of Specify the output file (of) instead of stdout\n"
+ "\n"
+ "-r --reusable Allow reuse of scanner definitions.\n"
+ "\n"
+ "-s --nested-ifs Generate nested ifs for some switches. Many compilers\n"
+ " need this assist to generate better code.\n"
+ "\n"
+ "-t th --type-header=th Generate a type header file (th) with type definitions.\n"
+ "\n"
+ "-u --unicode Generate a parser that supports UTF-32. The generated code\n"
+ " can deal with any valid Unicode character up to 0x10FFFF.\n"
+ " In this mode re2c assumes that input character size is 4 bytes.\n"
+ " This switch is incompatible with -e, -w, -x and -8. It implies -s.\n"
+ "\n"
+ "-v --version Show version information.\n"
+ "\n"
+ "-V --vernum Show version as one number.\n"
+ "\n"
+ "-w --wide-chars Generate a parser that supports UCS-2. The generated code can\n"
+ " deal with any valid Unicode character up to 0xFFFF. In this mode\n"
+ " re2c assumes that input character size is 2 bytes. This switch is\n"
+ " incompatible with -e, -x, -u and -8. It implies -s."
+ "\n"
+ "-x --utf-16 Generate a parser that supports UTF-16. The generated code can\n"
+ " deal with any valid Unicode character up to 0x10FFFF. In this mode\n"
+ " re2c assumes that input character size is 2 bytes. This switch is\n"
+ " incompatible with -e, -w, -u and -8. It implies -s."
+ "\n"
+ "-8 --utf-8 Generate a parser that supports UTF-8. The generated code can\n"
+ " deal with any valid Unicode character up to 0x10FFFF. In this mode\n"
+ " re2c assumes that input character size is 1 byte. This switch is\n"
+ " incompatible with -e, -w, -x and -u."
+ "\n"
+ "--no-generation-date Suppress date output in the generated file.\n"
+ "\n"
+ "--no-version Suppress version output in the generated file.\n"
+ "\n"
+ "--case-insensitive All strings are case insensitive, so all \"-expressions\n"
+ " are treated in the same way '-expressions are.\n"
+ "\n"
+ "--case-inverted Invert the meaning of single and double quoted strings.\n"
+ " With this switch single quotes are case sensitive and\n"
+ " double quotes are case insensitive.\n"
+ "\n"
+ "--encoding-policy ep Specify what re2c should do when given bad code unit.\n"
+ " ep can be one of the following: fail, substitute, ignore.\n"
+ "\n"
+ "--input i Specify re2c input API.\n"
+ " i can be one of the following: default, custom.\n"
+ "\n"
+ "--skeleton Instead of embedding re2c-generated code into C/C++ source,\n"
+ " generate a self-contained program for the same DFA.\n"
+ " Most useful for correctness and performance testing.\n"
+ "\n"
+ "--empty-class policy What to do if user inputs empty character class. policy can be\n"
+ " one of the following: 'match-empty' (match empty input, default),\n"
+ " 'match-none' (fail to match on any input), 'error' (compilation\n"
+ " error). Note that there are various ways to construct empty class,\n"
+ " e.g: [], [^\\x00-\\xFF], [\\x00-\\xFF]\\[\\x00-\\xFF].\n"
+ "\n"
+ "--dfa-minimization \n"
+ " Internal algorithm used by re2c to minimize DFA (defaults to\n"
+ " 'moore'). Both table filling and Moore's algorithms should\n"
+ " produce identical DFA (up to states relabelling). Table filling\n"
+ " algorithm is much simpler and slower; it serves as a reference\n"
+ " implementation.\n"
+ "\n"
+ "-1 --single-pass Deprecated and does nothing (single pass is by default now).\n"
+ "\n"
+ "-W Turn on all warnings.\n"
+ "\n"
+ "-Werror Turn warnings into errors. Note that this option along doesn't\n"
+ " turn on any warnings, it only affects those warnings that have\n"
+ " been turned on so far or will be turned on later.\n"
+ "\n"
+ "-W Turn on individual warning.\n"
+ "\n"
+ "-Wno- Turn off individual warning.\n"
+ "\n"
+ "-Werror- Turn on individual warning and treat it as error (this implies\n"
+ " '-W').\n"
+ "\n"
+ "-Wno-error- Don't treat this particular warning as error. This doesn't turn\n"
+ " off the warning itself.\n"
+ "\n"
+ "Warnings:\n"
+ "\n"
+ "-Wcondition-order Warn if the generated program makes implicit assumptions about\n"
+ " condition numbering. One should use either '-t, --type-header'\n"
+ " option or '/*!types:re2c*/' directive to generate mapping of\n"
+ " condition names to numbers and use autogenerated condition names.\n"
+ "\n"
+ "-Wempty-character-class Warn if regular expression contains empty character class. From\n"
+ " the rational point of view trying to match empty character class\n"
+ " makes no sense: it should always fail. However, for backwards\n"
+ " compatibility reasons re2c allows empty character class and treats\n"
+ " it as empty string. Use '--empty-class' option to change default\n"
+ " behaviour.\n"
+ "\n"
+ "-Wmatch-empty-string Warn if regular expression in a rule is nullable (matches empty\n"
+ " string). If DFA runs in a loop and empty match is unintentional\n"
+ " (input position in not advanced manually), lexer may get stuck\n"
+ " in eternal loop.\n"
+ "\n"
+ "-Wswapped-range Warn if range lower bound is greater that upper bound. Default\n"
+ " re2c behaviour is to silently swap range bounds.\n"
+ "\n"
+ "-Wundefined-control-flow\n"
+ " Warn if some input strings cause undefined control flow in lexer\n"
+ " (the faulty patterns are reported). This is the most dangerous\n"
+ " and common mistake. It can be easily fixed by adding default rule\n"
+ " '*' (this rule has the lowest priority, matches any code unit\n"
+ " and consumes exactly one code unit).\n"
+ "\n"
+ "-Wuseless-escape Warn if a symbol is escaped when it shouldn't be. By default re2c\n"
+ " silently ignores escape, but this may as well indicate a typo\n"
+ " or an error in escape sequence.\n"
+ "\n"
+ );
+}
+
+void vernum ()
+{
+ std::string vernum (PACKAGE_VERSION);
+ if (vernum[1] == '.')
+ {
+ vernum.insert(0, "0");
+ }
+ vernum.erase(2, 1);
+ if (vernum[3] == '.')
+ {
+ vernum.insert(2, "0");
+ }
+ vernum.erase(4, 1);
+ if (vernum.length() < 6 || vernum[5] < '0' || vernum[5] > '9')
+ {
+ vernum.insert(4, "0");
+ }
+ vernum.resize(6, '0');
+
+ printf ("%s\n", vernum.c_str ());
+}
+
+void version ()
+{
+ printf ("re2c %s\n", PACKAGE_VERSION);
+}
+
+std::string incond (const std::string & cond)
+{
+ std::string s;
+ if (!cond.empty ())
+ {
+ s += "in condition '";
+ s += cond;
+ s += "' ";
+ }
+ return s;
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/conf/msg.h b/tools/re2c/src/conf/msg.h
new file mode 100644
index 000000000..b70555239
--- /dev/null
+++ b/tools/re2c/src/conf/msg.h
@@ -0,0 +1,24 @@
+#ifndef _RE2C_CONF_MSG_
+#define _RE2C_CONF_MSG_
+
+#include
+
+#include "src/util/attribute.h"
+#include "src/util/c99_stdint.h"
+
+namespace re2c {
+
+void error (const char * fmt, ...) RE2C_GXX_ATTRIBUTE ((format (printf, 1, 2)));
+void error_encoding ();
+void error_arg (const char * option);
+void warning_start (uint32_t line, bool error);
+void warning_end (const char * type, bool error);
+void warning (const char * type, uint32_t line, bool error, const char * fmt, ...) RE2C_GXX_ATTRIBUTE ((format (printf, 4, 5)));
+void usage ();
+void vernum ();
+void version ();
+std::string incond (const std::string & cond);
+
+} // namespace re2c
+
+#endif // _RE2C_CONF_MSG_
diff --git a/tools/re2c/src/conf/opt.cc b/tools/re2c/src/conf/opt.cc
new file mode 100644
index 000000000..fa65ceaa8
--- /dev/null
+++ b/tools/re2c/src/conf/opt.cc
@@ -0,0 +1,331 @@
+#include "src/conf/msg.h"
+#include "src/conf/opt.h"
+
+namespace re2c
+{
+
+Opt opts;
+
+opt_t::opt_t ()
+#define OPT1(type, name, value) : name (value)
+#define OPT(type, name, value) , name (value)
+ RE2C_OPTS
+#undef OPT1
+#undef OPT
+{}
+
+opt_t::opt_t (const opt_t & opt)
+#define OPT1(type, name, value) : name (opt.name)
+#define OPT(type, name, value) , name (opt.name)
+ RE2C_OPTS
+#undef OPT1
+#undef OPT
+{}
+
+opt_t & opt_t::operator = (const opt_t & opt)
+{
+#define OPT1 OPT
+#define OPT(type, name, value) name = opt.name;
+ RE2C_OPTS
+#undef OPT1
+#undef OPT
+ return *this;
+}
+
+void opt_t::fix ()
+{
+ // some options either make no sense or must have fixed value
+ // with current target: reset them to default
+ switch (target)
+ {
+ case DOT:
+ // default code generation options
+ sFlag = Opt::baseopt.sFlag;
+ bFlag = Opt::baseopt.bFlag;
+ gFlag = Opt::baseopt.gFlag;
+ cGotoThreshold = Opt::baseopt.cGotoThreshold;
+ // default environment-insensitive formatting
+ yybmHexTable = Opt::baseopt.yybmHexTable;
+ // fallthrough
+ case SKELETON:
+ // default line information
+ iFlag = Opt::baseopt.iFlag;
+ // default environment-sensitive formatting
+ topIndent = Opt::baseopt.topIndent;
+ indString = Opt::baseopt.indString;
+ condDivider = Opt::baseopt.condDivider;
+ condDividerParam = Opt::baseopt.condDividerParam;
+ // default environment bindings
+ tFlag = Opt::baseopt.tFlag;
+ header_file = Opt::baseopt.header_file;
+ yycondtype = Opt::baseopt.yycondtype;
+ cond_get = Opt::baseopt.cond_get;
+ cond_get_naked = Opt::baseopt.cond_get_naked;
+ cond_set = Opt::baseopt.cond_set;
+ cond_set_arg = Opt::baseopt.cond_set_arg;
+ cond_set_naked = Opt::baseopt.cond_set_naked;
+ yyctable = Opt::baseopt.yyctable;
+ condPrefix = Opt::baseopt.condPrefix;
+ condEnumPrefix = Opt::baseopt.condEnumPrefix;
+ condGoto = Opt::baseopt.condGoto;
+ condGotoParam = Opt::baseopt.condGotoParam;
+ fFlag = Opt::baseopt.fFlag;
+ state_get = Opt::baseopt.state_get;
+ state_get_naked = Opt::baseopt.state_get_naked;
+ state_set = Opt::baseopt.state_set;
+ state_set_arg = Opt::baseopt.state_set_arg;
+ state_set_naked = Opt::baseopt.state_set_naked;
+ yyfilllabel = Opt::baseopt.yyfilllabel;
+ yynext = Opt::baseopt.yynext;
+ yyaccept = Opt::baseopt.yyaccept;
+ bUseStateAbort = Opt::baseopt.bUseStateAbort;
+ bUseStateNext = Opt::baseopt.bUseStateNext;
+ yybm = Opt::baseopt.yybm;
+ yytarget = Opt::baseopt.yytarget;
+ input_api = Opt::baseopt.input_api;
+ yycursor = Opt::baseopt.yycursor;
+ yymarker = Opt::baseopt.yymarker;
+ yyctxmarker = Opt::baseopt.yyctxmarker;
+ yylimit = Opt::baseopt.yylimit;
+ yypeek = Opt::baseopt.yypeek;
+ yyskip = Opt::baseopt.yyskip;
+ yybackup = Opt::baseopt.yybackup;
+ yybackupctx = Opt::baseopt.yybackupctx;
+ yyrestore = Opt::baseopt.yyrestore;
+ yyrestorectx = Opt::baseopt.yyrestorectx;
+ yylessthan = Opt::baseopt.yylessthan;
+ dFlag = Opt::baseopt.dFlag;
+ yydebug = Opt::baseopt.yydebug;
+ yyctype = Opt::baseopt.yyctype;
+ yych = Opt::baseopt.yych;
+ bEmitYYCh = Opt::baseopt.bEmitYYCh;
+ yychConversion = Opt::baseopt.yychConversion;
+ fill = Opt::baseopt.fill;
+ fill_use = Opt::baseopt.fill_use;
+ fill_check = Opt::baseopt.fill_check;
+ fill_arg = Opt::baseopt.fill_arg;
+ fill_arg_use = Opt::baseopt.fill_arg_use;
+ fill_naked = Opt::baseopt.fill_naked;
+ labelPrefix = Opt::baseopt.labelPrefix;
+ break;
+ default:
+ break;
+ }
+
+ if (bCaseInsensitive)
+ {
+ bCaseInverted = Opt::baseopt.bCaseInverted;
+ }
+
+ // respect hierarchy
+ if (!cFlag)
+ {
+ tFlag = Opt::baseopt.tFlag;
+ header_file = Opt::baseopt.header_file;
+ yycondtype = Opt::baseopt.yycondtype;
+ cond_get = Opt::baseopt.cond_get;
+ cond_get_naked = Opt::baseopt.cond_get_naked;
+ cond_set = Opt::baseopt.cond_set;
+ cond_set_arg = Opt::baseopt.cond_set_arg;
+ cond_set_naked = Opt::baseopt.cond_set_naked;
+ yyctable = Opt::baseopt.yyctable;
+ condPrefix = Opt::baseopt.condPrefix;
+ condEnumPrefix = Opt::baseopt.condEnumPrefix;
+ condDivider = Opt::baseopt.condDivider;
+ condDividerParam = Opt::baseopt.condDividerParam;
+ condGoto = Opt::baseopt.condGoto;
+ condGotoParam = Opt::baseopt.condGotoParam;
+ }
+ if (!fFlag)
+ {
+ state_get = Opt::baseopt.state_get;
+ state_get_naked = Opt::baseopt.state_get_naked;
+ state_set = Opt::baseopt.state_set;
+ state_set_arg = Opt::baseopt.state_set_arg;
+ state_set_naked = Opt::baseopt.state_set_naked;
+ yyfilllabel = Opt::baseopt.yyfilllabel;
+ yynext = Opt::baseopt.yynext;
+ yyaccept = Opt::baseopt.yyaccept;
+ bUseStateAbort = Opt::baseopt.bUseStateAbort;
+ bUseStateNext = Opt::baseopt.bUseStateNext;
+ }
+ if (!bFlag)
+ {
+ yybmHexTable = Opt::baseopt.yybmHexTable;
+ yybm = Opt::baseopt.yybm;
+ }
+ if (!gFlag)
+ {
+ cGotoThreshold = Opt::baseopt.cGotoThreshold;
+ yytarget = Opt::baseopt.yytarget;
+ }
+ if (input_api.type () != InputAPI::DEFAULT)
+ {
+ yycursor = Opt::baseopt.yycursor;
+ yymarker = Opt::baseopt.yymarker;
+ yyctxmarker = Opt::baseopt.yyctxmarker;
+ yylimit = Opt::baseopt.yylimit;
+ }
+ if (input_api.type () != InputAPI::CUSTOM)
+ {
+ yypeek = Opt::baseopt.yypeek;
+ yyskip = Opt::baseopt.yyskip;
+ yybackup = Opt::baseopt.yybackup;
+ yybackupctx = Opt::baseopt.yybackupctx;
+ yyrestore = Opt::baseopt.yyrestore;
+ yyrestorectx = Opt::baseopt.yyrestorectx;
+ yylessthan = Opt::baseopt.yylessthan;
+ }
+ if (!dFlag)
+ {
+ yydebug = Opt::baseopt.yydebug;
+ }
+ if (!fill_use)
+ {
+ fill = Opt::baseopt.fill;
+ fill_check = Opt::baseopt.fill_check;
+ fill_arg = Opt::baseopt.fill_arg;
+ fill_arg_use = Opt::baseopt.fill_arg_use;
+ fill_naked = Opt::baseopt.fill_naked;
+ }
+
+ // force individual options
+ switch (target)
+ {
+ case DOT:
+ iFlag = true;
+ break;
+ case SKELETON:
+ iFlag = true;
+ input_api.set (InputAPI::CUSTOM);
+ indString = " ";
+ topIndent = 2;
+ break;
+ default:
+ break;
+ }
+ switch (encoding.type ())
+ {
+ case Enc::UCS2:
+ case Enc::UTF16:
+ case Enc::UTF32:
+ sFlag = true;
+ break;
+ default:
+ break;
+ }
+ if (bFlag)
+ {
+ sFlag = true;
+ }
+ if (gFlag)
+ {
+ bFlag = true;
+ sFlag = true;
+ }
+ if (header_file != NULL)
+ {
+ tFlag = true;
+ }
+}
+
+realopt_t::realopt_t (useropt_t & opt)
+ : real ()
+ , user (opt)
+{}
+
+const opt_t * realopt_t::operator -> ()
+{
+ sync ();
+ return ℜ
+}
+
+void realopt_t::sync ()
+{
+ if (user.diverge)
+ {
+ real = user.opt;
+ real.fix ();
+ user.diverge = false;
+ }
+}
+
+useropt_t::useropt_t ()
+ : opt ()
+ , diverge (true)
+{}
+
+opt_t * useropt_t::operator -> ()
+{
+ diverge = true;
+ return &opt;
+}
+
+const opt_t Opt::baseopt;
+
+bool Opt::source (const char * s)
+{
+ if (source_file)
+ {
+ error ("multiple source files: %s, %s", source_file, s);
+ return false;
+ }
+ else
+ {
+ source_file = s;
+ return true;
+ }
+}
+
+bool Opt::output (const char * s)
+{
+ if (output_file)
+ {
+ error ("multiple output files: %s, %s", output_file, s);
+ return false;
+ }
+ else
+ {
+ output_file = s;
+ return true;
+ }
+}
+
+void Opt::reset_encoding (const Enc & enc)
+{
+ useropt->encoding = enc;
+}
+
+void Opt::reset_mapCodeName ()
+{
+ // historically arranged set of names
+ // no actual reason why these particular options should be reset
+ useropt->cond_get = Opt::baseopt.cond_get;
+ useropt->cond_set = Opt::baseopt.cond_set;
+ useropt->fill = Opt::baseopt.fill;
+ useropt->state_get = Opt::baseopt.state_get;
+ useropt->state_set = Opt::baseopt.state_set;
+ useropt->yybackup = Opt::baseopt.yybackup;
+ useropt->yybackupctx = Opt::baseopt.yybackupctx;
+ useropt->yycondtype = Opt::baseopt.yycondtype;
+ useropt->yyctxmarker = Opt::baseopt.yyctxmarker;
+ useropt->yyctype = Opt::baseopt.yyctype;
+ useropt->yycursor = Opt::baseopt.yycursor;
+ useropt->yydebug = Opt::baseopt.yydebug;
+ useropt->yylessthan = Opt::baseopt.yylessthan;
+ useropt->yylimit = Opt::baseopt.yylimit;
+ useropt->yymarker = Opt::baseopt.yymarker;
+ useropt->yypeek = Opt::baseopt.yypeek;
+ useropt->yyrestore = Opt::baseopt.yyrestore;
+ useropt->yyrestorectx = Opt::baseopt.yyrestorectx;
+ useropt->yyskip = Opt::baseopt.yyskip;
+ useropt->yyfilllabel = Opt::baseopt.yyfilllabel;
+ useropt->yynext = Opt::baseopt.yynext;
+ useropt->yyaccept = Opt::baseopt.yyaccept;
+ useropt->yybm = Opt::baseopt.yybm;
+ useropt->yych = Opt::baseopt.yych;
+ useropt->yyctable = Opt::baseopt.yyctable;
+ useropt->yytarget = Opt::baseopt.yytarget;
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/conf/opt.h b/tools/re2c/src/conf/opt.h
new file mode 100644
index 000000000..30ab21e55
--- /dev/null
+++ b/tools/re2c/src/conf/opt.h
@@ -0,0 +1,218 @@
+#ifndef _RE2C_CONF_OPT_
+#define _RE2C_CONF_OPT_
+
+#include "src/util/c99_stdint.h"
+#include
+#include
+
+#include "src/codegen/input_api.h"
+#include "src/ir/dfa/dfa.h"
+#include "src/ir/regexp/empty_class_policy.h"
+#include "src/ir/regexp/encoding/enc.h"
+#include "src/util/forbid_copy.h"
+
+namespace re2c
+{
+
+#define RE2C_OPTS \
+ /* target */ \
+ OPT1 (opt_t::target_t, target, CODE) \
+ /* fingerprint */ \
+ OPT (bool, bNoGenerationDate, false) \
+ OPT (bool, version, true) \
+ /* regular expressions */ \
+ OPT (Enc, encoding, Enc ()) \
+ OPT (bool, bCaseInsensitive, false) \
+ OPT (bool, bCaseInverted, false) \
+ OPT (empty_class_policy_t, empty_class_policy, EMPTY_CLASS_MATCH_EMPTY) \
+ /* conditions */ \
+ OPT (bool, cFlag, false) \
+ OPT (bool, tFlag, false) \
+ OPT (const char *, header_file, NULL) \
+ OPT (std::string, yycondtype, "YYCONDTYPE") \
+ OPT (std::string, cond_get, "YYGETCONDITION") \
+ OPT (bool, cond_get_naked, false) \
+ OPT (std::string, cond_set, "YYSETCONDITION" ) \
+ OPT (std::string, cond_set_arg, "@@" ) \
+ OPT (bool, cond_set_naked, false ) \
+ OPT (std::string, yyctable, "yyctable") \
+ OPT (std::string, condPrefix, "yyc_") \
+ OPT (std::string, condEnumPrefix, "yyc") \
+ OPT (std::string, condDivider, "/* *********************************** */") \
+ OPT (std::string, condDividerParam, "@@") \
+ OPT (std::string, condGoto, "goto @@;") \
+ OPT (std::string, condGotoParam, "@@") \
+ /* states */ \
+ OPT (bool, fFlag, false) \
+ OPT (std::string, state_get, "YYGETSTATE") \
+ OPT (bool, state_get_naked, false) \
+ OPT (std::string, state_set, "YYSETSTATE") \
+ OPT (std::string, state_set_arg, "@@") \
+ OPT (bool, state_set_naked, false) \
+ OPT (std::string, yyfilllabel, "yyFillLabel") \
+ OPT (std::string, yynext, "yyNext") \
+ OPT (std::string, yyaccept, "yyaccept") \
+ OPT (bool, bUseStateAbort, false) \
+ OPT (bool, bUseStateNext, false) \
+ /* reuse */ \
+ OPT (bool, rFlag, false) \
+ /* partial flex syntax support */ \
+ OPT (bool, FFlag, false) \
+ /* code generation */ \
+ OPT (bool, sFlag, false) \
+ OPT (bool, bFlag, false) \
+ OPT (std::string, yybm, "yybm") \
+ OPT (bool, yybmHexTable, false) \
+ OPT (bool, gFlag, false) \
+ OPT (std::string, yytarget, "yytarget") \
+ OPT (uint32_t, cGotoThreshold, 9) \
+ /* formatting */ \
+ OPT (uint32_t, topIndent, 0) \
+ OPT (std::string, indString, "\t") \
+ /* input API */ \
+ OPT (InputAPI, input_api, InputAPI ()) \
+ OPT (std::string, yycursor, "YYCURSOR") \
+ OPT (std::string, yymarker, "YYMARKER") \
+ OPT (std::string, yyctxmarker, "YYCTXMARKER") \
+ OPT (std::string, yylimit, "YYLIMIT") \
+ OPT (std::string, yypeek, "YYPEEK") \
+ OPT (std::string, yyskip, "YYSKIP") \
+ OPT (std::string, yybackup, "YYBACKUP") \
+ OPT (std::string, yybackupctx, "YYBACKUPCTX") \
+ OPT (std::string, yyrestore, "YYRESTORE") \
+ OPT (std::string, yyrestorectx, "YYRESTORECTX") \
+ OPT (std::string, yylessthan, "YYLESSTHAN") \
+ /* #line directives */ \
+ OPT (bool, iFlag, false) \
+ /* debug */ \
+ OPT (bool, dFlag, false) \
+ OPT (std::string, yydebug, "YYDEBUG") \
+ /* yych */ \
+ OPT (std::string, yyctype, "YYCTYPE") \
+ OPT (std::string, yych, "yych") \
+ OPT (bool, bEmitYYCh, true) \
+ OPT (bool, yychConversion, false) \
+ /* YYFILL */ \
+ OPT (std::string, fill, "YYFILL") \
+ OPT (bool, fill_use, true) \
+ OPT (bool, fill_check, true) \
+ OPT (std::string, fill_arg, "@@") \
+ OPT (bool, fill_arg_use, true) \
+ OPT (bool, fill_naked, false) \
+ /* labels */ \
+ OPT (std::string, labelPrefix, "yy") \
+ /* internals */ \
+ OPT (dfa_minimization_t, dfa_minimization, DFA_MINIMIZATION_MOORE)
+
+struct opt_t
+{
+ enum target_t
+ {
+ CODE,
+ DOT,
+ SKELETON
+ };
+
+#define OPT1 OPT
+#define OPT(type, name, value) type name;
+ RE2C_OPTS
+#undef OPT1
+#undef OPT
+
+ opt_t ();
+ opt_t (const opt_t & opt);
+ opt_t & operator = (const opt_t & opt);
+ void fix ();
+};
+
+class useropt_t;
+class realopt_t
+{
+ opt_t real;
+ useropt_t & user;
+public:
+ realopt_t (useropt_t & opt);
+ const opt_t * operator -> ();
+ void sync ();
+};
+
+class useropt_t
+{
+ opt_t opt;
+ bool diverge;
+public:
+ useropt_t ();
+ opt_t * operator -> ();
+ friend void realopt_t::sync ();
+};
+
+struct Opt
+{
+ static const opt_t baseopt;
+
+ const char * source_file;
+ const char * output_file;
+
+private:
+ useropt_t useropt;
+ realopt_t realopt;
+
+public:
+ Opt ()
+ : source_file (NULL)
+ , output_file (NULL)
+ , useropt ()
+ , realopt (useropt)
+ {}
+
+ // read-only access, forces options syncronization
+ const opt_t * operator -> ()
+ {
+ return realopt.operator -> ();
+ }
+
+ bool source (const char * s);
+ bool output (const char * s);
+
+ // Inplace configurations are applied immediately when parsed.
+ // This is very bad: first, re2c behaviour is changed in the middle
+ // of the block; second, config is resynced too often (every
+ // attempt to read config that has been updated results in
+ // automatic resync). It is much better to set all options at once.
+ bool set_encoding (Enc::type_t t) { return useropt->encoding.set (t); }
+ void unset_encoding (Enc::type_t t) { useropt->encoding.unset (t); }
+ void set_encoding_policy (Enc::policy_t p) { useropt->encoding.setPolicy (p); }
+ void set_input_api (InputAPI::type_t t) { useropt->input_api.set (t); }
+#define OPT1 OPT
+#define OPT(type, name, value) void set_##name (type arg) { useropt->name = arg; }
+ RE2C_OPTS
+#undef OPT1
+#undef OPT
+
+ // helpers
+ std::string yychConversion ()
+ {
+ return realopt->yychConversion
+ ? "(" + realopt->yyctype + ")"
+ : "";
+ }
+
+ // bad temporary hacks, should be fixed by proper scoping of config (parts).
+ void reset_encoding (const Enc & enc);
+ void reset_mapCodeName ();
+
+ FORBID_COPY (Opt);
+};
+
+enum parse_opts_t
+{
+ OK,
+ EXIT_OK,
+ EXIT_FAIL
+};
+
+parse_opts_t parse_opts (char ** argv, Opt & opts);
+
+} // namespace re2c
+
+#endif // _RE2C_CONF_OPT_
diff --git a/tools/re2c/src/conf/parse_opts.cc b/tools/re2c/src/conf/parse_opts.cc
new file mode 100644
index 000000000..9eb07989e
--- /dev/null
+++ b/tools/re2c/src/conf/parse_opts.cc
@@ -0,0 +1,2846 @@
+/* Generated by re2c 0.16 on Thu Jan 21 10:47:47 2016 */
+#line 1 "../src/conf/parse_opts.re"
+#include "src/codegen/input_api.h"
+#include "src/conf/msg.h"
+#include "src/conf/opt.h"
+#include "src/conf/warn.h"
+#include "src/globals.h"
+#include "src/ir/regexp/empty_class_policy.h"
+#include "src/ir/regexp/encoding/enc.h"
+
+namespace re2c
+{
+
+static inline bool next (char * & arg, char ** & argv)
+{
+ arg = *++argv;
+ return arg != NULL;
+}
+
+parse_opts_t parse_opts (char ** argv, Opt & opts)
+{
+#define YYCTYPE unsigned char
+ char * YYCURSOR;
+ char * YYMARKER;
+ Warn::option_t option;
+
+#line 31 "../src/conf/parse_opts.re"
+
+
+opt:
+ if (!next (YYCURSOR, argv))
+ {
+ goto end;
+ }
+
+#line 37 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ };
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych <= 0x00) goto yy2;
+ if (yych == '-') goto yy5;
+ goto yy4;
+yy2:
+ ++YYCURSOR;
+yy3:
+#line 40 "../src/conf/parse_opts.re"
+ {
+ error ("bad option: %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 87 "src/conf/parse_opts.cc"
+yy4:
+ yyaccept = 0;
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ goto yy10;
+yy5:
+ ++YYCURSOR;
+ if ((yych = (YYCTYPE)*YYCURSOR) <= '-') {
+ if (yych <= 0x00) goto yy11;
+ if (yych >= '-') goto yy13;
+ } else {
+ if (yych == 'W') goto yy15;
+ }
+#line 63 "../src/conf/parse_opts.re"
+ { goto opt_short; }
+#line 102 "src/conf/parse_opts.cc"
+yy7:
+ ++YYCURSOR;
+#line 61 "../src/conf/parse_opts.re"
+ { if (!opts.source (*argv)) return EXIT_FAIL; goto opt; }
+#line 107 "src/conf/parse_opts.cc"
+yy9:
+ ++YYCURSOR;
+ yych = (YYCTYPE)*YYCURSOR;
+yy10:
+ if (yybm[0+yych] & 128) {
+ goto yy9;
+ }
+ goto yy7;
+yy11:
+ ++YYCURSOR;
+#line 60 "../src/conf/parse_opts.re"
+ { if (!opts.source ("")) return EXIT_FAIL; goto opt; }
+#line 120 "src/conf/parse_opts.cc"
+yy13:
+ ++YYCURSOR;
+ if ((yych = (YYCTYPE)*YYCURSOR) <= 0x00) goto yy17;
+#line 64 "../src/conf/parse_opts.re"
+ { goto opt_long; }
+#line 126 "src/conf/parse_opts.cc"
+yy15:
+ yyaccept = 1;
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych <= 'e') {
+ if (yych <= 0x00) goto yy19;
+ if (yych >= 'e') goto yy21;
+ } else {
+ if (yych == 'n') goto yy23;
+ }
+yy16:
+#line 68 "../src/conf/parse_opts.re"
+ { option = Warn::W; goto opt_warn; }
+#line 139 "src/conf/parse_opts.cc"
+yy17:
+ ++YYCURSOR;
+#line 46 "../src/conf/parse_opts.re"
+ {
+ // all remaining arguments are non-options
+ // so they must be input files
+ // re2c expects exactly one input file
+ for (char * f; next (f, argv);)
+ {
+ if (!opts.source (f))
+ {
+ return EXIT_FAIL;
+ }
+ }
+ goto end;
+ }
+#line 156 "src/conf/parse_opts.cc"
+yy19:
+ ++YYCURSOR;
+#line 66 "../src/conf/parse_opts.re"
+ { warn.set_all (); goto opt; }
+#line 161 "src/conf/parse_opts.cc"
+yy21:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy24;
+yy22:
+ YYCURSOR = YYMARKER;
+ if (yyaccept <= 1) {
+ if (yyaccept == 0) {
+ goto yy3;
+ } else {
+ goto yy16;
+ }
+ } else {
+ goto yy28;
+ }
+yy23:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy25;
+ goto yy22;
+yy24:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy26;
+ goto yy22;
+yy25:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy27;
+ goto yy22;
+yy26:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy29;
+ goto yy22;
+yy27:
+ yyaccept = 2;
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'e') goto yy30;
+yy28:
+#line 69 "../src/conf/parse_opts.re"
+ { option = Warn::WNO; goto opt_warn; }
+#line 199 "src/conf/parse_opts.cc"
+yy29:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy31;
+ goto yy22;
+yy30:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy32;
+ goto yy22;
+yy31:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy33;
+ if (yych == '-') goto yy35;
+ goto yy22;
+yy32:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy37;
+ goto yy22;
+yy33:
+ ++YYCURSOR;
+#line 67 "../src/conf/parse_opts.re"
+ { warn.set_all_error (); goto opt; }
+#line 221 "src/conf/parse_opts.cc"
+yy35:
+ ++YYCURSOR;
+#line 70 "../src/conf/parse_opts.re"
+ { option = Warn::WERROR; goto opt_warn; }
+#line 226 "src/conf/parse_opts.cc"
+yy37:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych != 'o') goto yy22;
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych != 'r') goto yy22;
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych != '-') goto yy22;
+ ++YYCURSOR;
+#line 71 "../src/conf/parse_opts.re"
+ { option = Warn::WNOERROR; goto opt_warn; }
+#line 237 "src/conf/parse_opts.cc"
+}
+#line 72 "../src/conf/parse_opts.re"
+
+
+opt_warn:
+
+#line 244 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ switch (yych) {
+ case 'c': goto yy46;
+ case 'e': goto yy47;
+ case 'm': goto yy48;
+ case 's': goto yy49;
+ case 'u': goto yy50;
+ default: goto yy44;
+ }
+yy44:
+ ++YYCURSOR;
+yy45:
+#line 77 "../src/conf/parse_opts.re"
+ {
+ error ("bad warning: %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 264 "src/conf/parse_opts.cc"
+yy46:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'o') goto yy51;
+ goto yy45;
+yy47:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'm') goto yy53;
+ goto yy45;
+yy48:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'a') goto yy54;
+ goto yy45;
+yy49:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'w') goto yy55;
+ goto yy45;
+yy50:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'n') goto yy56;
+ if (yych == 's') goto yy57;
+ goto yy45;
+yy51:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy58;
+yy52:
+ YYCURSOR = YYMARKER;
+ goto yy45;
+yy53:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy59;
+ goto yy52;
+yy54:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy60;
+ goto yy52;
+yy55:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy61;
+ goto yy52;
+yy56:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy62;
+ if (yych == 'r') goto yy63;
+ goto yy52;
+yy57:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy64;
+ goto yy52;
+yy58:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy65;
+ goto yy52;
+yy59:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy66;
+ goto yy52;
+yy60:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy67;
+ goto yy52;
+yy61:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy68;
+ goto yy52;
+yy62:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy69;
+ goto yy52;
+yy63:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy70;
+ goto yy52;
+yy64:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy71;
+ goto yy52;
+yy65:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy72;
+ goto yy52;
+yy66:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'y') goto yy73;
+ goto yy52;
+yy67:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'h') goto yy74;
+ goto yy52;
+yy68:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy75;
+ goto yy52;
+yy69:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'f') goto yy76;
+ goto yy52;
+yy70:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy77;
+ goto yy52;
+yy71:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy78;
+ goto yy52;
+yy72:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy79;
+ goto yy52;
+yy73:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy80;
+ goto yy52;
+yy74:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy81;
+ goto yy52;
+yy75:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy82;
+ goto yy52;
+yy76:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy83;
+ goto yy52;
+yy77:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy84;
+ goto yy52;
+yy78:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy85;
+ goto yy52;
+yy79:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy86;
+ goto yy52;
+yy80:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy87;
+ goto yy52;
+yy81:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy88;
+ goto yy52;
+yy82:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy89;
+ goto yy52;
+yy83:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy90;
+ goto yy52;
+yy84:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'h') goto yy91;
+ goto yy52;
+yy85:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy92;
+ goto yy52;
+yy86:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy93;
+ goto yy52;
+yy87:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'h') goto yy94;
+ goto yy52;
+yy88:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy95;
+ goto yy52;
+yy89:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy96;
+ goto yy52;
+yy90:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy97;
+ goto yy52;
+yy91:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy98;
+ goto yy52;
+yy92:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy99;
+ goto yy52;
+yy93:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy100;
+ goto yy52;
+yy94:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy101;
+ goto yy52;
+yy95:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy102;
+ goto yy52;
+yy96:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy103;
+ goto yy52;
+yy97:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy104;
+ goto yy52;
+yy98:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy105;
+ goto yy52;
+yy99:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy106;
+ goto yy52;
+yy100:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy107;
+ goto yy52;
+yy101:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy108;
+ goto yy52;
+yy102:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy109;
+ goto yy52;
+yy103:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy110;
+ goto yy52;
+yy104:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy111;
+ goto yy52;
+yy105:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy112;
+ goto yy52;
+yy106:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy113;
+ goto yy52;
+yy107:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy114;
+ goto yy52;
+yy108:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy115;
+ goto yy52;
+yy109:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'y') goto yy116;
+ goto yy52;
+yy110:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy117;
+ goto yy52;
+yy111:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy118;
+ goto yy52;
+yy112:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy119;
+ goto yy52;
+yy113:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy120;
+ goto yy52;
+yy114:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy121;
+ goto yy52;
+yy115:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy122;
+ goto yy52;
+yy116:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy123;
+ goto yy52;
+yy117:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy124;
+ goto yy52;
+yy118:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy125;
+ goto yy52;
+yy119:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy126;
+ goto yy52;
+yy120:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy127;
+ goto yy52;
+yy121:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy128;
+ goto yy52;
+yy122:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy129;
+ goto yy52;
+yy123:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy130;
+ goto yy52;
+yy124:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy131;
+ goto yy52;
+yy125:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy132;
+ goto yy52;
+yy126:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy133;
+ goto yy52;
+yy127:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy134;
+ goto yy52;
+yy128:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy135;
+ goto yy52;
+yy129:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy136;
+ goto yy52;
+yy130:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy137;
+ goto yy52;
+yy131:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy138;
+ goto yy52;
+yy132:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy140;
+ goto yy52;
+yy133:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy141;
+ goto yy52;
+yy134:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy142;
+ goto yy52;
+yy135:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy143;
+ goto yy52;
+yy136:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy144;
+ goto yy52;
+yy137:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy145;
+ goto yy52;
+yy138:
+ ++YYCURSOR;
+#line 84 "../src/conf/parse_opts.re"
+ { warn.set (Warn::SWAPPED_RANGE, option); goto opt; }
+#line 637 "src/conf/parse_opts.cc"
+yy140:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy146;
+ goto yy52;
+yy141:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy147;
+ goto yy52;
+yy142:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy148;
+ goto yy52;
+yy143:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy150;
+ goto yy52;
+yy144:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy152;
+ goto yy52;
+yy145:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy153;
+ goto yy52;
+yy146:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy154;
+ goto yy52;
+yy147:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy155;
+ goto yy52;
+yy148:
+ ++YYCURSOR;
+#line 87 "../src/conf/parse_opts.re"
+ { warn.set (Warn::USELESS_ESCAPE, option); goto opt; }
+#line 674 "src/conf/parse_opts.cc"
+yy150:
+ ++YYCURSOR;
+#line 81 "../src/conf/parse_opts.re"
+ { warn.set (Warn::CONDITION_ORDER, option); goto opt; }
+#line 679 "src/conf/parse_opts.cc"
+yy152:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy156;
+ goto yy52;
+yy153:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy157;
+ goto yy52;
+yy154:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy158;
+ goto yy52;
+yy155:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy159;
+ goto yy52;
+yy156:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy160;
+ goto yy52;
+yy157:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy161;
+ goto yy52;
+yy158:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy162;
+ goto yy52;
+yy159:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy163;
+ goto yy52;
+yy160:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy165;
+ goto yy52;
+yy161:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy166;
+ goto yy52;
+yy162:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'f') goto yy168;
+ goto yy52;
+yy163:
+ ++YYCURSOR;
+#line 86 "../src/conf/parse_opts.re"
+ { warn.set (Warn::UNREACHABLE_RULES, option); goto opt; }
+#line 728 "src/conf/parse_opts.cc"
+yy165:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy169;
+ goto yy52;
+yy166:
+ ++YYCURSOR;
+#line 83 "../src/conf/parse_opts.re"
+ { warn.set (Warn::MATCH_EMPTY_STRING, option); goto opt; }
+#line 737 "src/conf/parse_opts.cc"
+yy168:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy170;
+ goto yy52;
+yy169:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy171;
+ goto yy52;
+yy170:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy172;
+ goto yy52;
+yy171:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy173;
+ goto yy52;
+yy172:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'w') goto yy175;
+ goto yy52;
+yy173:
+ ++YYCURSOR;
+#line 82 "../src/conf/parse_opts.re"
+ { warn.set (Warn::EMPTY_CHARACTER_CLASS, option); goto opt; }
+#line 762 "src/conf/parse_opts.cc"
+yy175:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych >= 0x01) goto yy52;
+ ++YYCURSOR;
+#line 85 "../src/conf/parse_opts.re"
+ { warn.set (Warn::UNDEFINED_CONTROL_FLOW, option); goto opt; }
+#line 769 "src/conf/parse_opts.cc"
+}
+#line 88 "../src/conf/parse_opts.re"
+
+
+opt_short:
+
+#line 776 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych <= 'b') {
+ if (yych <= 'C') {
+ if (yych <= '7') {
+ if (yych <= 0x00) goto yy180;
+ if (yych == '1') goto yy184;
+ goto yy182;
+ } else {
+ if (yych <= '8') goto yy186;
+ if (yych == '?') goto yy188;
+ goto yy182;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych <= 'D') goto yy190;
+ if (yych == 'F') goto yy192;
+ goto yy182;
+ } else {
+ if (yych <= 'U') {
+ if (yych <= 'S') goto yy194;
+ goto yy182;
+ } else {
+ if (yych <= 'V') goto yy196;
+ if (yych <= 'a') goto yy182;
+ goto yy198;
+ }
+ }
+ }
+ } else {
+ if (yych <= 'o') {
+ if (yych <= 'f') {
+ if (yych <= 'c') goto yy200;
+ if (yych <= 'd') goto yy202;
+ if (yych <= 'e') goto yy204;
+ goto yy206;
+ } else {
+ if (yych <= 'h') {
+ if (yych <= 'g') goto yy208;
+ goto yy188;
+ } else {
+ if (yych <= 'i') goto yy210;
+ if (yych <= 'n') goto yy182;
+ goto yy212;
+ }
+ }
+ } else {
+ if (yych <= 't') {
+ if (yych <= 'q') goto yy182;
+ if (yych <= 'r') goto yy214;
+ if (yych <= 's') goto yy216;
+ goto yy218;
+ } else {
+ if (yych <= 'v') {
+ if (yych <= 'u') goto yy220;
+ goto yy222;
+ } else {
+ if (yych <= 'w') goto yy224;
+ if (yych <= 'x') goto yy226;
+ goto yy182;
+ }
+ }
+ }
+ }
+yy180:
+ ++YYCURSOR;
+#line 97 "../src/conf/parse_opts.re"
+ { goto opt; }
+#line 846 "src/conf/parse_opts.cc"
+yy182:
+ ++YYCURSOR;
+#line 93 "../src/conf/parse_opts.re"
+ {
+ error ("bad short option: %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 854 "src/conf/parse_opts.cc"
+yy184:
+ ++YYCURSOR;
+#line 121 "../src/conf/parse_opts.re"
+ { goto opt_short; }
+#line 859 "src/conf/parse_opts.cc"
+yy186:
+ ++YYCURSOR;
+#line 116 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UTF8)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+#line 864 "src/conf/parse_opts.cc"
+yy188:
+ ++YYCURSOR;
+#line 98 "../src/conf/parse_opts.re"
+ { usage (); return EXIT_OK; }
+#line 869 "src/conf/parse_opts.cc"
+yy190:
+ ++YYCURSOR;
+#line 104 "../src/conf/parse_opts.re"
+ { opts.set_target (opt_t::DOT); goto opt_short; }
+#line 874 "src/conf/parse_opts.cc"
+yy192:
+ ++YYCURSOR;
+#line 106 "../src/conf/parse_opts.re"
+ { opts.set_FFlag (true); goto opt_short; }
+#line 879 "src/conf/parse_opts.cc"
+yy194:
+ ++YYCURSOR;
+#line 111 "../src/conf/parse_opts.re"
+ { opts.set_target (opt_t::SKELETON); goto opt_short; }
+#line 884 "src/conf/parse_opts.cc"
+yy196:
+ ++YYCURSOR;
+#line 100 "../src/conf/parse_opts.re"
+ { vernum (); return EXIT_OK; }
+#line 889 "src/conf/parse_opts.cc"
+yy198:
+ ++YYCURSOR;
+#line 101 "../src/conf/parse_opts.re"
+ { opts.set_bFlag (true); goto opt_short; }
+#line 894 "src/conf/parse_opts.cc"
+yy200:
+ ++YYCURSOR;
+#line 102 "../src/conf/parse_opts.re"
+ { opts.set_cFlag (true); goto opt_short; }
+#line 899 "src/conf/parse_opts.cc"
+yy202:
+ ++YYCURSOR;
+#line 103 "../src/conf/parse_opts.re"
+ { opts.set_dFlag (true); goto opt_short; }
+#line 904 "src/conf/parse_opts.cc"
+yy204:
+ ++YYCURSOR;
+#line 112 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::EBCDIC)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+#line 909 "src/conf/parse_opts.cc"
+yy206:
+ ++YYCURSOR;
+#line 105 "../src/conf/parse_opts.re"
+ { opts.set_fFlag (true); goto opt_short; }
+#line 914 "src/conf/parse_opts.cc"
+yy208:
+ ++YYCURSOR;
+#line 107 "../src/conf/parse_opts.re"
+ { opts.set_gFlag (true); goto opt_short; }
+#line 919 "src/conf/parse_opts.cc"
+yy210:
+ ++YYCURSOR;
+#line 108 "../src/conf/parse_opts.re"
+ { opts.set_iFlag (true); goto opt_short; }
+#line 924 "src/conf/parse_opts.cc"
+yy212:
+ ++YYCURSOR;
+ if ((yych = (YYCTYPE)*YYCURSOR) <= 0x00) goto yy228;
+#line 118 "../src/conf/parse_opts.re"
+ { *argv = YYCURSOR; goto opt_output; }
+#line 930 "src/conf/parse_opts.cc"
+yy214:
+ ++YYCURSOR;
+#line 109 "../src/conf/parse_opts.re"
+ { opts.set_rFlag (true); goto opt_short; }
+#line 935 "src/conf/parse_opts.cc"
+yy216:
+ ++YYCURSOR;
+#line 110 "../src/conf/parse_opts.re"
+ { opts.set_sFlag (true); goto opt_short; }
+#line 940 "src/conf/parse_opts.cc"
+yy218:
+ ++YYCURSOR;
+ if ((yych = (YYCTYPE)*YYCURSOR) <= 0x00) goto yy230;
+#line 120 "../src/conf/parse_opts.re"
+ { *argv = YYCURSOR; goto opt_header; }
+#line 946 "src/conf/parse_opts.cc"
+yy220:
+ ++YYCURSOR;
+#line 113 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UTF32)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+#line 951 "src/conf/parse_opts.cc"
+yy222:
+ ++YYCURSOR;
+#line 99 "../src/conf/parse_opts.re"
+ { version (); return EXIT_OK; }
+#line 956 "src/conf/parse_opts.cc"
+yy224:
+ ++YYCURSOR;
+#line 114 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UCS2)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+#line 961 "src/conf/parse_opts.cc"
+yy226:
+ ++YYCURSOR;
+#line 115 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UTF16)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+#line 966 "src/conf/parse_opts.cc"
+yy228:
+ ++YYCURSOR;
+#line 117 "../src/conf/parse_opts.re"
+ { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; }
+#line 971 "src/conf/parse_opts.cc"
+yy230:
+ ++YYCURSOR;
+#line 119 "../src/conf/parse_opts.re"
+ { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; }
+#line 976 "src/conf/parse_opts.cc"
+}
+#line 122 "../src/conf/parse_opts.re"
+
+
+opt_long:
+
+#line 983 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ switch (yych) {
+ case 'b': goto yy236;
+ case 'c': goto yy237;
+ case 'd': goto yy238;
+ case 'e': goto yy239;
+ case 'f': goto yy240;
+ case 'h': goto yy241;
+ case 'i': goto yy242;
+ case 'n': goto yy243;
+ case 'o': goto yy244;
+ case 'r': goto yy245;
+ case 's': goto yy246;
+ case 't': goto yy247;
+ case 'u': goto yy248;
+ case 'v': goto yy249;
+ case 'w': goto yy250;
+ default: goto yy234;
+ }
+yy234:
+ ++YYCURSOR;
+yy235:
+#line 127 "../src/conf/parse_opts.re"
+ {
+ error ("bad long option: %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 1013 "src/conf/parse_opts.cc"
+yy236:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'i') goto yy251;
+ goto yy235;
+yy237:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'a') goto yy253;
+ if (yych == 'o') goto yy254;
+ goto yy235;
+yy238:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych <= 'd') goto yy235;
+ if (yych <= 'e') goto yy255;
+ if (yych <= 'f') goto yy256;
+ goto yy235;
+yy239:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych <= 'l') {
+ if (yych == 'c') goto yy257;
+ goto yy235;
+ } else {
+ if (yych <= 'm') goto yy258;
+ if (yych <= 'n') goto yy259;
+ goto yy235;
+ }
+yy240:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'l') goto yy260;
+ goto yy235;
+yy241:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'e') goto yy261;
+ goto yy235;
+yy242:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'n') goto yy262;
+ goto yy235;
+yy243:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'e') goto yy263;
+ if (yych == 'o') goto yy264;
+ goto yy235;
+yy244:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'u') goto yy265;
+ goto yy235;
+yy245:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'e') goto yy266;
+ goto yy235;
+yy246:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych <= 'j') {
+ if (yych == 'i') goto yy267;
+ goto yy235;
+ } else {
+ if (yych <= 'k') goto yy268;
+ if (yych == 't') goto yy269;
+ goto yy235;
+ }
+yy247:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'y') goto yy270;
+ goto yy235;
+yy248:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'n') goto yy271;
+ if (yych == 't') goto yy272;
+ goto yy235;
+yy249:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'e') goto yy273;
+ goto yy235;
+yy250:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'i') goto yy274;
+ goto yy235;
+yy251:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy275;
+yy252:
+ YYCURSOR = YYMARKER;
+ goto yy235;
+yy253:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy276;
+ goto yy252;
+yy254:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy277;
+ goto yy252;
+yy255:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy278;
+ goto yy252;
+yy256:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy279;
+ goto yy252;
+yy257:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy280;
+ goto yy252;
+yy258:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy281;
+ if (yych == 'p') goto yy282;
+ goto yy252;
+yy259:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy283;
+ goto yy252;
+yy260:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy284;
+ goto yy252;
+yy261:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy285;
+ goto yy252;
+yy262:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy286;
+ goto yy252;
+yy263:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy287;
+ goto yy252;
+yy264:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy288;
+ goto yy252;
+yy265:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy289;
+ goto yy252;
+yy266:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy290;
+ goto yy252;
+yy267:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy291;
+ goto yy252;
+yy268:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy292;
+ goto yy252;
+yy269:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy293;
+ if (yych == 'o') goto yy294;
+ goto yy252;
+yy270:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy295;
+ goto yy252;
+yy271:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy296;
+ goto yy252;
+yy272:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'f') goto yy297;
+ goto yy252;
+yy273:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy298;
+ goto yy252;
+yy274:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy299;
+ goto yy252;
+yy275:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy300;
+ goto yy252;
+yy276:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy301;
+ goto yy252;
+yy277:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy302;
+ goto yy252;
+yy278:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy303;
+ goto yy252;
+yy279:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy304;
+ goto yy252;
+yy280:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy305;
+ goto yy252;
+yy281:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy307;
+ goto yy252;
+yy282:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy308;
+ goto yy252;
+yy283:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy309;
+ goto yy252;
+yy284:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'x') goto yy310;
+ goto yy252;
+yy285:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy311;
+ goto yy252;
+yy286:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy312;
+ goto yy252;
+yy287:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy313;
+ goto yy252;
+yy288:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 'f') {
+ if (yych == 'd') goto yy314;
+ goto yy252;
+ } else {
+ if (yych <= 'g') goto yy315;
+ if (yych == 'v') goto yy316;
+ goto yy252;
+ }
+yy289:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy317;
+ goto yy252;
+yy290:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy318;
+ goto yy252;
+yy291:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy319;
+ goto yy252;
+yy292:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy320;
+ goto yy252;
+yy293:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy321;
+ goto yy252;
+yy294:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy322;
+ goto yy252;
+yy295:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy323;
+ goto yy252;
+yy296:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy324;
+ goto yy252;
+yy297:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy325;
+ goto yy252;
+yy298:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy326;
+ if (yych == 's') goto yy327;
+ goto yy252;
+yy299:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy328;
+ goto yy252;
+yy300:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'v') goto yy329;
+ goto yy252;
+yy301:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy330;
+ goto yy252;
+yy302:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy331;
+ goto yy252;
+yy303:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy332;
+ goto yy252;
+yy304:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy333;
+ goto yy252;
+yy305:
+ ++YYCURSOR;
+#line 149 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::EBCDIC)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+#line 1318 "src/conf/parse_opts.cc"
+yy307:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy334;
+ goto yy252;
+yy308:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'y') goto yy335;
+ goto yy252;
+yy309:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy336;
+ goto yy252;
+yy310:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy337;
+ goto yy252;
+yy311:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy338;
+ goto yy252;
+yy312:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy340;
+ goto yy252;
+yy313:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy341;
+ goto yy252;
+yy314:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy342;
+ goto yy252;
+yy315:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy343;
+ goto yy252;
+yy316:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy344;
+ goto yy252;
+yy317:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy345;
+ goto yy252;
+yy318:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy346;
+ goto yy252;
+yy319:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy347;
+ goto yy252;
+yy320:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy348;
+ goto yy252;
+yy321:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy349;
+ goto yy252;
+yy322:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy350;
+ goto yy252;
+yy323:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy351;
+ goto yy252;
+yy324:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy352;
+ goto yy252;
+yy325:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '1') goto yy353;
+ if (yych == '8') goto yy354;
+ goto yy252;
+yy326:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy355;
+ goto yy252;
+yy327:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy356;
+ goto yy252;
+yy328:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy357;
+ goto yy252;
+yy329:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy358;
+ goto yy252;
+yy330:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy359;
+ goto yy252;
+yy331:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy360;
+ goto yy252;
+yy332:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy361;
+ goto yy252;
+yy333:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy362;
+ goto yy252;
+yy334:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy363;
+ goto yy252;
+yy335:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy364;
+ goto yy252;
+yy336:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy365;
+ goto yy252;
+yy337:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy366;
+ goto yy252;
+yy338:
+ ++YYCURSOR;
+#line 131 "../src/conf/parse_opts.re"
+ { usage (); return EXIT_OK; }
+#line 1448 "src/conf/parse_opts.cc"
+yy340:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy367;
+ goto yy252;
+yy341:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy369;
+ goto yy252;
+yy342:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy370;
+ goto yy252;
+yy343:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy371;
+ goto yy252;
+yy344:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy372;
+ goto yy252;
+yy345:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy373;
+ goto yy252;
+yy346:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy374;
+ goto yy252;
+yy347:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy375;
+ goto yy252;
+yy348:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy376;
+ goto yy252;
+yy349:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy377;
+ goto yy252;
+yy350:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy378;
+ goto yy252;
+yy351:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'h') goto yy379;
+ goto yy252;
+yy352:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy380;
+ goto yy252;
+yy353:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '6') goto yy381;
+ goto yy252;
+yy354:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy382;
+ goto yy252;
+yy355:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy384;
+ goto yy252;
+yy356:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy385;
+ goto yy252;
+yy357:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy386;
+ goto yy252;
+yy358:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy387;
+ goto yy252;
+yy359:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy388;
+ goto yy252;
+yy360:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy389;
+ goto yy252;
+yy361:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy390;
+ goto yy252;
+yy362:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy391;
+ goto yy252;
+yy363:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy392;
+ goto yy252;
+yy364:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy393;
+ goto yy252;
+yy365:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy394;
+ goto yy252;
+yy366:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'y') goto yy395;
+ goto yy252;
+yy367:
+ ++YYCURSOR;
+#line 157 "../src/conf/parse_opts.re"
+ { goto opt_input; }
+#line 1561 "src/conf/parse_opts.cc"
+yy369:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy396;
+ goto yy252;
+yy370:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy397;
+ goto yy252;
+yy371:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy398;
+ goto yy252;
+yy372:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy399;
+ goto yy252;
+yy373:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy400;
+ goto yy252;
+yy374:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy402;
+ goto yy252;
+yy375:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy403;
+ goto yy252;
+yy376:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy404;
+ goto yy252;
+yy377:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy405;
+ goto yy252;
+yy378:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy406;
+ goto yy252;
+yy379:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy407;
+ goto yy252;
+yy380:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy408;
+ goto yy252;
+yy381:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy409;
+ goto yy252;
+yy382:
+ ++YYCURSOR;
+#line 153 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UTF8)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+#line 1618 "src/conf/parse_opts.cc"
+yy384:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy411;
+ goto yy252;
+yy385:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy413;
+ goto yy252;
+yy386:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'h') goto yy414;
+ goto yy252;
+yy387:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy415;
+ goto yy252;
+yy388:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy416;
+ if (yych == 'v') goto yy417;
+ goto yy252;
+yy389:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy418;
+ goto yy252;
+yy390:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy419;
+ goto yy252;
+yy391:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy420;
+ goto yy252;
+yy392:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy421;
+ goto yy252;
+yy393:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy422;
+ goto yy252;
+yy394:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy423;
+ goto yy252;
+yy395:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy424;
+ goto yy252;
+yy396:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy425;
+ goto yy252;
+yy397:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy426;
+ goto yy252;
+yy398:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy427;
+ goto yy252;
+yy399:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy428;
+ goto yy252;
+yy400:
+ ++YYCURSOR;
+#line 154 "../src/conf/parse_opts.re"
+ { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; }
+#line 1688 "src/conf/parse_opts.cc"
+yy402:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy429;
+ goto yy252;
+yy403:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy430;
+ goto yy252;
+yy404:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy431;
+ goto yy252;
+yy405:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy432;
+ goto yy252;
+yy406:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy433;
+ goto yy252;
+yy407:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy434;
+ goto yy252;
+yy408:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy435;
+ goto yy252;
+yy409:
+ ++YYCURSOR;
+#line 152 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UTF16)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+#line 1721 "src/conf/parse_opts.cc"
+yy411:
+ ++YYCURSOR;
+#line 133 "../src/conf/parse_opts.re"
+ { vernum (); return EXIT_OK; }
+#line 1726 "src/conf/parse_opts.cc"
+yy413:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy437;
+ goto yy252;
+yy414:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy439;
+ goto yy252;
+yy415:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy440;
+ goto yy252;
+yy416:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy441;
+ goto yy252;
+yy417:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy442;
+ goto yy252;
+yy418:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy443;
+ goto yy252;
+yy419:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy444;
+ goto yy252;
+yy420:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy445;
+ goto yy252;
+yy421:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy446;
+ goto yy252;
+yy422:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy448;
+ goto yy252;
+yy423:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy449;
+ goto yy252;
+yy424:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy450;
+ goto yy252;
+yy425:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'f') goto yy451;
+ goto yy252;
+yy426:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy452;
+ goto yy252;
+yy427:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy453;
+ goto yy252;
+yy428:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy454;
+ goto yy252;
+yy429:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy455;
+ goto yy252;
+yy430:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy457;
+ goto yy252;
+yy431:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy458;
+ goto yy252;
+yy432:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy460;
+ goto yy252;
+yy433:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy461;
+ goto yy252;
+yy434:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy462;
+ goto yy252;
+yy435:
+ ++YYCURSOR;
+#line 150 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UTF32)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+#line 1819 "src/conf/parse_opts.cc"
+yy437:
+ ++YYCURSOR;
+#line 132 "../src/conf/parse_opts.re"
+ { version (); return EXIT_OK; }
+#line 1824 "src/conf/parse_opts.cc"
+yy439:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy463;
+ goto yy252;
+yy440:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy464;
+ goto yy252;
+yy441:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy465;
+ goto yy252;
+yy442:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy466;
+ goto yy252;
+yy443:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'g') goto yy467;
+ goto yy252;
+yy444:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy468;
+ goto yy252;
+yy445:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy469;
+ goto yy252;
+yy446:
+ ++YYCURSOR;
+#line 137 "../src/conf/parse_opts.re"
+ { opts.set_target (opt_t::DOT); goto opt; }
+#line 1857 "src/conf/parse_opts.cc"
+yy448:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy470;
+ goto yy252;
+yy449:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy471;
+ goto yy252;
+yy450:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy472;
+ goto yy252;
+yy451:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy473;
+ goto yy252;
+yy452:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy474;
+ goto yy252;
+yy453:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy475;
+ goto yy252;
+yy454:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy476;
+ goto yy252;
+yy455:
+ ++YYCURSOR;
+#line 142 "../src/conf/parse_opts.re"
+ { opts.set_rFlag (true); goto opt; }
+#line 1890 "src/conf/parse_opts.cc"
+yy457:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy477;
+ goto yy252;
+yy458:
+ ++YYCURSOR;
+#line 148 "../src/conf/parse_opts.re"
+ { opts.set_target (opt_t::SKELETON); goto opt; }
+#line 1899 "src/conf/parse_opts.cc"
+yy460:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy478;
+ goto yy252;
+yy461:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy479;
+ goto yy252;
+yy462:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy480;
+ goto yy252;
+yy463:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy481;
+ goto yy252;
+yy464:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy482;
+ goto yy252;
+yy465:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy483;
+ goto yy252;
+yy466:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy484;
+ goto yy252;
+yy467:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy485;
+ goto yy252;
+yy468:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy486;
+ goto yy252;
+yy469:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'z') goto yy487;
+ goto yy252;
+yy470:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy488;
+ goto yy252;
+yy471:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy489;
+ goto yy252;
+yy472:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'x') goto yy490;
+ goto yy252;
+yy473:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy491;
+ goto yy252;
+yy474:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy493;
+ goto yy252;
+yy475:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy494;
+ goto yy252;
+yy476:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy495;
+ goto yy252;
+yy477:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy497;
+ goto yy252;
+yy478:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy498;
+ goto yy252;
+yy479:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy499;
+ goto yy252;
+yy480:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy500;
+ goto yy252;
+yy481:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy501;
+ goto yy252;
+yy482:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy503;
+ goto yy252;
+yy483:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy505;
+ goto yy252;
+yy484:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy506;
+ goto yy252;
+yy485:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy507;
+ goto yy252;
+yy486:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy508;
+ goto yy252;
+yy487:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy509;
+ goto yy252;
+yy488:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy510;
+ goto yy252;
+yy489:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy512;
+ goto yy252;
+yy490:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy513;
+ goto yy252;
+yy491:
+ ++YYCURSOR;
+#line 143 "../src/conf/parse_opts.re"
+ { opts.set_sFlag (true); goto opt; }
+#line 2028 "src/conf/parse_opts.cc"
+yy493:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'f') goto yy515;
+ goto yy252;
+yy494:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy516;
+ goto yy252;
+yy495:
+ ++YYCURSOR;
+#line 145 "../src/conf/parse_opts.re"
+ { opts.set_version (false); goto opt; }
+#line 2041 "src/conf/parse_opts.cc"
+yy497:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy517;
+ goto yy252;
+yy498:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy519;
+ goto yy252;
+yy499:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy520;
+ goto yy252;
+yy500:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy521;
+ goto yy252;
+yy501:
+ ++YYCURSOR;
+#line 151 "../src/conf/parse_opts.re"
+ { if (!opts.set_encoding (Enc::UCS2)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+#line 2062 "src/conf/parse_opts.cc"
+yy503:
+ ++YYCURSOR;
+#line 134 "../src/conf/parse_opts.re"
+ { opts.set_bFlag (true); goto opt; }
+#line 2067 "src/conf/parse_opts.cc"
+yy505:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy523;
+ goto yy252;
+yy506:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy524;
+ goto yy252;
+yy507:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy525;
+ goto yy252;
+yy508:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy526;
+ goto yy252;
+yy509:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy528;
+ goto yy252;
+yy510:
+ ++YYCURSOR;
+#line 158 "../src/conf/parse_opts.re"
+ { goto opt_empty_class; }
+#line 2092 "src/conf/parse_opts.cc"
+yy512:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy529;
+ goto yy252;
+yy513:
+ ++YYCURSOR;
+#line 139 "../src/conf/parse_opts.re"
+ { opts.set_FFlag (true); goto opt; }
+#line 2101 "src/conf/parse_opts.cc"
+yy515:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy530;
+ goto yy252;
+yy516:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy531;
+ goto yy252;
+yy517:
+ ++YYCURSOR;
+#line 160 "../src/conf/parse_opts.re"
+ { goto opt; }
+#line 2114 "src/conf/parse_opts.cc"
+yy519:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy532;
+ goto yy252;
+yy520:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy533;
+ goto yy252;
+yy521:
+ ++YYCURSOR;
+#line 155 "../src/conf/parse_opts.re"
+ { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; }
+#line 2127 "src/conf/parse_opts.cc"
+yy523:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy534;
+ goto yy252;
+yy524:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy535;
+ goto yy252;
+yy525:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy537;
+ goto yy252;
+yy526:
+ ++YYCURSOR;
+#line 136 "../src/conf/parse_opts.re"
+ { opts.set_dFlag (true); goto opt; }
+#line 2144 "src/conf/parse_opts.cc"
+yy528:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy538;
+ goto yy252;
+yy529:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy539;
+ goto yy252;
+yy530:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy540;
+ goto yy252;
+yy531:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy542;
+ goto yy252;
+yy532:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy543;
+ goto yy252;
+yy533:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy544;
+ goto yy252;
+yy534:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'v') goto yy545;
+ goto yy252;
+yy535:
+ ++YYCURSOR;
+#line 147 "../src/conf/parse_opts.re"
+ { opts.set_bCaseInverted (true); goto opt; }
+#line 2177 "src/conf/parse_opts.cc"
+yy537:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy546;
+ goto yy252;
+yy538:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy548;
+ goto yy252;
+yy539:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'y') goto yy549;
+ goto yy252;
+yy540:
+ ++YYCURSOR;
+#line 141 "../src/conf/parse_opts.re"
+ { opts.set_iFlag (true); goto opt; }
+#line 2194 "src/conf/parse_opts.cc"
+yy542:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'd') goto yy550;
+ goto yy252;
+yy543:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy551;
+ goto yy252;
+yy544:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy552;
+ goto yy252;
+yy545:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy554;
+ goto yy252;
+yy546:
+ ++YYCURSOR;
+#line 140 "../src/conf/parse_opts.re"
+ { opts.set_gFlag (true); goto opt; }
+#line 2215 "src/conf/parse_opts.cc"
+yy548:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy555;
+ goto yy252;
+yy549:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy556;
+ goto yy252;
+yy550:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy558;
+ goto yy252;
+yy551:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy559;
+ goto yy252;
+yy552:
+ ++YYCURSOR;
+#line 138 "../src/conf/parse_opts.re"
+ { opts.set_fFlag (true); goto opt; }
+#line 2236 "src/conf/parse_opts.cc"
+yy554:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy560;
+ goto yy252;
+yy555:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy562;
+ goto yy252;
+yy556:
+ ++YYCURSOR;
+#line 156 "../src/conf/parse_opts.re"
+ { goto opt_encoding_policy; }
+#line 2249 "src/conf/parse_opts.cc"
+yy558:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy564;
+ goto yy252;
+yy559:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy565;
+ goto yy252;
+yy560:
+ ++YYCURSOR;
+#line 146 "../src/conf/parse_opts.re"
+ { opts.set_bCaseInsensitive (true); goto opt; }
+#line 2262 "src/conf/parse_opts.cc"
+yy562:
+ ++YYCURSOR;
+#line 159 "../src/conf/parse_opts.re"
+ { goto opt_dfa_minimization; }
+#line 2267 "src/conf/parse_opts.cc"
+yy564:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy567;
+ goto yy252;
+yy565:
+ ++YYCURSOR;
+#line 135 "../src/conf/parse_opts.re"
+ { opts.set_cFlag (true); goto opt; }
+#line 2276 "src/conf/parse_opts.cc"
+yy567:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych >= 0x01) goto yy252;
+ ++YYCURSOR;
+#line 144 "../src/conf/parse_opts.re"
+ { opts.set_bNoGenerationDate (true); goto opt; }
+#line 2283 "src/conf/parse_opts.cc"
+}
+#line 161 "../src/conf/parse_opts.re"
+
+
+opt_output:
+
+#line 2290 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ static const unsigned char yybm[] = {
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ };
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych <= 0x00) goto yy572;
+ if (yych != '-') goto yy574;
+yy572:
+ ++YYCURSOR;
+#line 166 "../src/conf/parse_opts.re"
+ {
+ error ("bad argument to option -o, --output: %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 2337 "src/conf/parse_opts.cc"
+yy574:
+ yych = (YYCTYPE)*++YYCURSOR;
+ goto yy578;
+yy575:
+ ++YYCURSOR;
+#line 170 "../src/conf/parse_opts.re"
+ { if (!opts.output (*argv)) return EXIT_FAIL; goto opt; }
+#line 2345 "src/conf/parse_opts.cc"
+yy577:
+ ++YYCURSOR;
+ yych = (YYCTYPE)*YYCURSOR;
+yy578:
+ if (yybm[0+yych] & 128) {
+ goto yy577;
+ }
+ goto yy575;
+}
+#line 171 "../src/conf/parse_opts.re"
+
+
+opt_header:
+
+#line 2360 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ static const unsigned char yybm[] = {
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ };
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych <= 0x00) goto yy581;
+ if (yych != '-') goto yy583;
+yy581:
+ ++YYCURSOR;
+#line 176 "../src/conf/parse_opts.re"
+ {
+ error ("bad argument to option -t, --type-header: %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 2407 "src/conf/parse_opts.cc"
+yy583:
+ yych = (YYCTYPE)*++YYCURSOR;
+ goto yy587;
+yy584:
+ ++YYCURSOR;
+#line 180 "../src/conf/parse_opts.re"
+ { opts.set_header_file (*argv); goto opt; }
+#line 2415 "src/conf/parse_opts.cc"
+yy586:
+ ++YYCURSOR;
+ yych = (YYCTYPE)*YYCURSOR;
+yy587:
+ if (yybm[0+yych] & 128) {
+ goto yy586;
+ }
+ goto yy584;
+}
+#line 181 "../src/conf/parse_opts.re"
+
+
+opt_encoding_policy:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--encoding-policy");
+ return EXIT_FAIL;
+ }
+
+#line 2435 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych <= 'h') {
+ if (yych == 'f') goto yy592;
+ } else {
+ if (yych <= 'i') goto yy593;
+ if (yych == 's') goto yy594;
+ }
+ ++YYCURSOR;
+yy591:
+#line 191 "../src/conf/parse_opts.re"
+ {
+ error ("bad argument to option --encoding-policy (expected: ignore | substitute | fail): %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 2452 "src/conf/parse_opts.cc"
+yy592:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'a') goto yy595;
+ goto yy591;
+yy593:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'g') goto yy597;
+ goto yy591;
+yy594:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'u') goto yy598;
+ goto yy591;
+yy595:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy599;
+yy596:
+ YYCURSOR = YYMARKER;
+ goto yy591;
+yy597:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy600;
+ goto yy596;
+yy598:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy601;
+ goto yy596;
+yy599:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy602;
+ goto yy596;
+yy600:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy603;
+ goto yy596;
+yy601:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy604;
+ goto yy596;
+yy602:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy605;
+ goto yy596;
+yy603:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy607;
+ goto yy596;
+yy604:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy608;
+ goto yy596;
+yy605:
+ ++YYCURSOR;
+#line 197 "../src/conf/parse_opts.re"
+ { opts.set_encoding_policy (Enc::POLICY_FAIL); goto opt; }
+#line 2507 "src/conf/parse_opts.cc"
+yy607:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy609;
+ goto yy596;
+yy608:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'i') goto yy610;
+ goto yy596;
+yy609:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy611;
+ goto yy596;
+yy610:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy613;
+ goto yy596;
+yy611:
+ ++YYCURSOR;
+#line 195 "../src/conf/parse_opts.re"
+ { opts.set_encoding_policy (Enc::POLICY_IGNORE); goto opt; }
+#line 2528 "src/conf/parse_opts.cc"
+yy613:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych != 'u') goto yy596;
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych != 't') goto yy596;
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych != 'e') goto yy596;
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych >= 0x01) goto yy596;
+ ++YYCURSOR;
+#line 196 "../src/conf/parse_opts.re"
+ { opts.set_encoding_policy (Enc::POLICY_SUBSTITUTE); goto opt; }
+#line 2541 "src/conf/parse_opts.cc"
+}
+#line 198 "../src/conf/parse_opts.re"
+
+
+opt_input:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--input");
+ return EXIT_FAIL;
+ }
+
+#line 2553 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych <= 'b') goto yy621;
+ if (yych <= 'c') goto yy623;
+ if (yych <= 'd') goto yy624;
+yy621:
+ ++YYCURSOR;
+yy622:
+#line 208 "../src/conf/parse_opts.re"
+ {
+ error ("bad argument to option --input (expected: default | custom): %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 2568 "src/conf/parse_opts.cc"
+yy623:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'u') goto yy625;
+ goto yy622;
+yy624:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'e') goto yy627;
+ goto yy622;
+yy625:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 's') goto yy628;
+yy626:
+ YYCURSOR = YYMARKER;
+ goto yy622;
+yy627:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'f') goto yy629;
+ goto yy626;
+yy628:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy630;
+ goto yy626;
+yy629:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'a') goto yy631;
+ goto yy626;
+yy630:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy632;
+ goto yy626;
+yy631:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'u') goto yy633;
+ goto yy626;
+yy632:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy634;
+ goto yy626;
+yy633:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy635;
+ goto yy626;
+yy634:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy636;
+ goto yy626;
+yy635:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy638;
+ goto yy626;
+yy636:
+ ++YYCURSOR;
+#line 213 "../src/conf/parse_opts.re"
+ { opts.set_input_api (InputAPI::CUSTOM); goto opt; }
+#line 2623 "src/conf/parse_opts.cc"
+yy638:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych >= 0x01) goto yy626;
+ ++YYCURSOR;
+#line 212 "../src/conf/parse_opts.re"
+ { opts.set_input_api (InputAPI::DEFAULT); goto opt; }
+#line 2630 "src/conf/parse_opts.cc"
+}
+#line 214 "../src/conf/parse_opts.re"
+
+
+opt_empty_class:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--empty-class");
+ return EXIT_FAIL;
+ }
+
+#line 2642 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych == 'e') goto yy645;
+ if (yych == 'm') goto yy646;
+ ++YYCURSOR;
+yy644:
+#line 224 "../src/conf/parse_opts.re"
+ {
+ error ("bad argument to option --empty-class (expected: match-empty | match-none | error): %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 2655 "src/conf/parse_opts.cc"
+yy645:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'r') goto yy647;
+ goto yy644;
+yy646:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'a') goto yy649;
+ goto yy644;
+yy647:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy650;
+yy648:
+ YYCURSOR = YYMARKER;
+ goto yy644;
+yy649:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy651;
+ goto yy648;
+yy650:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy652;
+ goto yy648;
+yy651:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'c') goto yy653;
+ goto yy648;
+yy652:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy654;
+ goto yy648;
+yy653:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'h') goto yy655;
+ goto yy648;
+yy654:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy656;
+ goto yy648;
+yy655:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == '-') goto yy658;
+ goto yy648;
+yy656:
+ ++YYCURSOR;
+#line 230 "../src/conf/parse_opts.re"
+ { opts.set_empty_class_policy (EMPTY_CLASS_ERROR); goto opt; }
+#line 2702 "src/conf/parse_opts.cc"
+yy658:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy659;
+ if (yych == 'n') goto yy660;
+ goto yy648;
+yy659:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'm') goto yy661;
+ goto yy648;
+yy660:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy662;
+ goto yy648;
+yy661:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'p') goto yy663;
+ goto yy648;
+yy662:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'n') goto yy664;
+ goto yy648;
+yy663:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 't') goto yy665;
+ goto yy648;
+yy664:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy666;
+ goto yy648;
+yy665:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'y') goto yy667;
+ goto yy648;
+yy666:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy668;
+ goto yy648;
+yy667:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy670;
+ goto yy648;
+yy668:
+ ++YYCURSOR;
+#line 229 "../src/conf/parse_opts.re"
+ { opts.set_empty_class_policy (EMPTY_CLASS_MATCH_NONE); goto opt; }
+#line 2748 "src/conf/parse_opts.cc"
+yy670:
+ ++YYCURSOR;
+#line 228 "../src/conf/parse_opts.re"
+ { opts.set_empty_class_policy (EMPTY_CLASS_MATCH_EMPTY); goto opt; }
+#line 2753 "src/conf/parse_opts.cc"
+}
+#line 231 "../src/conf/parse_opts.re"
+
+
+opt_dfa_minimization:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--minimization");
+ return EXIT_FAIL;
+ }
+
+#line 2765 "src/conf/parse_opts.cc"
+{
+ YYCTYPE yych;
+ yych = (YYCTYPE)*YYCURSOR;
+ if (yych == 'm') goto yy676;
+ if (yych == 't') goto yy677;
+ ++YYCURSOR;
+yy675:
+#line 241 "../src/conf/parse_opts.re"
+ {
+ error ("bad argument to option --dfa-minimization (expected: table | moore): %s", *argv);
+ return EXIT_FAIL;
+ }
+#line 2778 "src/conf/parse_opts.cc"
+yy676:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'o') goto yy678;
+ goto yy675;
+yy677:
+ yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR);
+ if (yych == 'a') goto yy680;
+ goto yy675;
+yy678:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'o') goto yy681;
+yy679:
+ YYCURSOR = YYMARKER;
+ goto yy675;
+yy680:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'b') goto yy682;
+ goto yy679;
+yy681:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'r') goto yy683;
+ goto yy679;
+yy682:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'l') goto yy684;
+ goto yy679;
+yy683:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy685;
+ goto yy679;
+yy684:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych == 'e') goto yy686;
+ goto yy679;
+yy685:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy687;
+ goto yy679;
+yy686:
+ yych = (YYCTYPE)*++YYCURSOR;
+ if (yych <= 0x00) goto yy689;
+ goto yy679;
+yy687:
+ ++YYCURSOR;
+#line 246 "../src/conf/parse_opts.re"
+ { opts.set_dfa_minimization (DFA_MINIMIZATION_MOORE); goto opt; }
+#line 2825 "src/conf/parse_opts.cc"
+yy689:
+ ++YYCURSOR;
+#line 245 "../src/conf/parse_opts.re"
+ { opts.set_dfa_minimization (DFA_MINIMIZATION_TABLE); goto opt; }
+#line 2830 "src/conf/parse_opts.cc"
+}
+#line 247 "../src/conf/parse_opts.re"
+
+
+end:
+ if (!opts.source_file)
+ {
+ error ("no source file");
+ return EXIT_FAIL;
+ }
+
+ return OK;
+
+#undef YYCTYPE
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/conf/parse_opts.re b/tools/re2c/src/conf/parse_opts.re
new file mode 100644
index 000000000..5ff3a2175
--- /dev/null
+++ b/tools/re2c/src/conf/parse_opts.re
@@ -0,0 +1,261 @@
+#include "src/codegen/input_api.h"
+#include "src/conf/msg.h"
+#include "src/conf/opt.h"
+#include "src/conf/warn.h"
+#include "src/globals.h"
+#include "src/ir/regexp/empty_class_policy.h"
+#include "src/ir/regexp/encoding/enc.h"
+
+namespace re2c
+{
+
+static inline bool next (char * & arg, char ** & argv)
+{
+ arg = *++argv;
+ return arg != NULL;
+}
+
+parse_opts_t parse_opts (char ** argv, Opt & opts)
+{
+#define YYCTYPE unsigned char
+ char * YYCURSOR;
+ char * YYMARKER;
+ Warn::option_t option;
+
+/*!re2c
+ re2c:yyfill:enable = 0;
+ re2c:yych:conversion = 1;
+
+ end = "\x00";
+ filename = [^\x00-] [^\x00]*;
+*/
+
+opt:
+ if (!next (YYCURSOR, argv))
+ {
+ goto end;
+ }
+/*!re2c
+ *
+ {
+ error ("bad option: %s", *argv);
+ return EXIT_FAIL;
+ }
+
+ "--" end
+ {
+ // all remaining arguments are non-options
+ // so they must be input files
+ // re2c expects exactly one input file
+ for (char * f; next (f, argv);)
+ {
+ if (!opts.source (f))
+ {
+ return EXIT_FAIL;
+ }
+ }
+ goto end;
+ }
+
+ "-" end { if (!opts.source ("")) return EXIT_FAIL; goto opt; }
+ filename end { if (!opts.source (*argv)) return EXIT_FAIL; goto opt; }
+
+ "-" { goto opt_short; }
+ "--" { goto opt_long; }
+
+ "-W" end { warn.set_all (); goto opt; }
+ "-Werror" end { warn.set_all_error (); goto opt; }
+ "-W" { option = Warn::W; goto opt_warn; }
+ "-Wno-" { option = Warn::WNO; goto opt_warn; }
+ "-Werror-" { option = Warn::WERROR; goto opt_warn; }
+ "-Wno-error-" { option = Warn::WNOERROR; goto opt_warn; }
+*/
+
+opt_warn:
+/*!re2c
+ *
+ {
+ error ("bad warning: %s", *argv);
+ return EXIT_FAIL;
+ }
+ "condition-order" end { warn.set (Warn::CONDITION_ORDER, option); goto opt; }
+ "empty-character-class" end { warn.set (Warn::EMPTY_CHARACTER_CLASS, option); goto opt; }
+ "match-empty-string" end { warn.set (Warn::MATCH_EMPTY_STRING, option); goto opt; }
+ "swapped-range" end { warn.set (Warn::SWAPPED_RANGE, option); goto opt; }
+ "undefined-control-flow" end { warn.set (Warn::UNDEFINED_CONTROL_FLOW, option); goto opt; }
+ "unreachable-rules" end { warn.set (Warn::UNREACHABLE_RULES, option); goto opt; }
+ "useless-escape" end { warn.set (Warn::USELESS_ESCAPE, option); goto opt; }
+*/
+
+opt_short:
+/*!re2c
+ *
+ {
+ error ("bad short option: %s", *argv);
+ return EXIT_FAIL;
+ }
+ end { goto opt; }
+ [?h] { usage (); return EXIT_OK; }
+ "v" { version (); return EXIT_OK; }
+ "V" { vernum (); return EXIT_OK; }
+ "b" { opts.set_bFlag (true); goto opt_short; }
+ "c" { opts.set_cFlag (true); goto opt_short; }
+ "d" { opts.set_dFlag (true); goto opt_short; }
+ "D" { opts.set_target (opt_t::DOT); goto opt_short; }
+ "f" { opts.set_fFlag (true); goto opt_short; }
+ "F" { opts.set_FFlag (true); goto opt_short; }
+ "g" { opts.set_gFlag (true); goto opt_short; }
+ "i" { opts.set_iFlag (true); goto opt_short; }
+ "r" { opts.set_rFlag (true); goto opt_short; }
+ "s" { opts.set_sFlag (true); goto opt_short; }
+ "S" { opts.set_target (opt_t::SKELETON); goto opt_short; }
+ "e" { if (!opts.set_encoding (Enc::EBCDIC)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+ "u" { if (!opts.set_encoding (Enc::UTF32)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+ "w" { if (!opts.set_encoding (Enc::UCS2)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+ "x" { if (!opts.set_encoding (Enc::UTF16)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+ "8" { if (!opts.set_encoding (Enc::UTF8)) { error_encoding (); return EXIT_FAIL; } goto opt_short; }
+ "o" end { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; }
+ "o" { *argv = YYCURSOR; goto opt_output; }
+ "t" end { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; }
+ "t" { *argv = YYCURSOR; goto opt_header; }
+ "1" { goto opt_short; } // deprecated
+*/
+
+opt_long:
+/*!re2c
+ *
+ {
+ error ("bad long option: %s", *argv);
+ return EXIT_FAIL;
+ }
+ "help" end { usage (); return EXIT_OK; }
+ "version" end { version (); return EXIT_OK; }
+ "vernum" end { vernum (); return EXIT_OK; }
+ "bit-vectors" end { opts.set_bFlag (true); goto opt; }
+ "start-conditions" end { opts.set_cFlag (true); goto opt; }
+ "debug-output" end { opts.set_dFlag (true); goto opt; }
+ "emit-dot" end { opts.set_target (opt_t::DOT); goto opt; }
+ "storable-state" end { opts.set_fFlag (true); goto opt; }
+ "flex-syntax" end { opts.set_FFlag (true); goto opt; }
+ "computed-gotos" end { opts.set_gFlag (true); goto opt; }
+ "no-debug-info" end { opts.set_iFlag (true); goto opt; }
+ "reusable" end { opts.set_rFlag (true); goto opt; }
+ "nested-ifs" end { opts.set_sFlag (true); goto opt; }
+ "no-generation-date" end { opts.set_bNoGenerationDate (true); goto opt; }
+ "no-version" end { opts.set_version (false); goto opt; }
+ "case-insensitive" end { opts.set_bCaseInsensitive (true); goto opt; }
+ "case-inverted" end { opts.set_bCaseInverted (true); goto opt; }
+ "skeleton" end { opts.set_target (opt_t::SKELETON); goto opt; }
+ "ecb" end { if (!opts.set_encoding (Enc::EBCDIC)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+ "unicode" end { if (!opts.set_encoding (Enc::UTF32)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+ "wide-chars" end { if (!opts.set_encoding (Enc::UCS2)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+ "utf-16" end { if (!opts.set_encoding (Enc::UTF16)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+ "utf-8" end { if (!opts.set_encoding (Enc::UTF8)) { error_encoding (); return EXIT_FAIL; } goto opt; }
+ "output" end { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; }
+ "type-header" end { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; }
+ "encoding-policy" end { goto opt_encoding_policy; }
+ "input" end { goto opt_input; }
+ "empty-class" end { goto opt_empty_class; }
+ "dfa-minimization" end { goto opt_dfa_minimization; }
+ "single-pass" end { goto opt; } // deprecated
+*/
+
+opt_output:
+/*!re2c
+ *
+ {
+ error ("bad argument to option -o, --output: %s", *argv);
+ return EXIT_FAIL;
+ }
+ filename end { if (!opts.output (*argv)) return EXIT_FAIL; goto opt; }
+*/
+
+opt_header:
+/*!re2c
+ *
+ {
+ error ("bad argument to option -t, --type-header: %s", *argv);
+ return EXIT_FAIL;
+ }
+ filename end { opts.set_header_file (*argv); goto opt; }
+*/
+
+opt_encoding_policy:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--encoding-policy");
+ return EXIT_FAIL;
+ }
+/*!re2c
+ *
+ {
+ error ("bad argument to option --encoding-policy (expected: ignore | substitute | fail): %s", *argv);
+ return EXIT_FAIL;
+ }
+ "ignore" end { opts.set_encoding_policy (Enc::POLICY_IGNORE); goto opt; }
+ "substitute" end { opts.set_encoding_policy (Enc::POLICY_SUBSTITUTE); goto opt; }
+ "fail" end { opts.set_encoding_policy (Enc::POLICY_FAIL); goto opt; }
+*/
+
+opt_input:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--input");
+ return EXIT_FAIL;
+ }
+/*!re2c
+ *
+ {
+ error ("bad argument to option --input (expected: default | custom): %s", *argv);
+ return EXIT_FAIL;
+ }
+ "default" end { opts.set_input_api (InputAPI::DEFAULT); goto opt; }
+ "custom" end { opts.set_input_api (InputAPI::CUSTOM); goto opt; }
+*/
+
+opt_empty_class:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--empty-class");
+ return EXIT_FAIL;
+ }
+/*!re2c
+ *
+ {
+ error ("bad argument to option --empty-class (expected: match-empty | match-none | error): %s", *argv);
+ return EXIT_FAIL;
+ }
+ "match-empty" end { opts.set_empty_class_policy (EMPTY_CLASS_MATCH_EMPTY); goto opt; }
+ "match-none" end { opts.set_empty_class_policy (EMPTY_CLASS_MATCH_NONE); goto opt; }
+ "error" end { opts.set_empty_class_policy (EMPTY_CLASS_ERROR); goto opt; }
+*/
+
+opt_dfa_minimization:
+ if (!next (YYCURSOR, argv))
+ {
+ error_arg ("--minimization");
+ return EXIT_FAIL;
+ }
+/*!re2c
+ *
+ {
+ error ("bad argument to option --dfa-minimization (expected: table | moore): %s", *argv);
+ return EXIT_FAIL;
+ }
+ "table" end { opts.set_dfa_minimization (DFA_MINIMIZATION_TABLE); goto opt; }
+ "moore" end { opts.set_dfa_minimization (DFA_MINIMIZATION_MOORE); goto opt; }
+*/
+
+end:
+ if (!opts.source_file)
+ {
+ error ("no source file");
+ return EXIT_FAIL;
+ }
+
+ return OK;
+
+#undef YYCTYPE
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/conf/warn.cc b/tools/re2c/src/conf/warn.cc
new file mode 100644
index 000000000..e309f26d6
--- /dev/null
+++ b/tools/re2c/src/conf/warn.cc
@@ -0,0 +1,200 @@
+#include
+#include
+#include
+#include
+
+#include "src/conf/msg.h"
+#include "src/conf/warn.h"
+
+namespace re2c {
+
+Warn warn;
+
+const uint32_t Warn::SILENT = 0;
+const uint32_t Warn::WARNING = 1u << 0;
+const uint32_t Warn::ERROR = 1u << 1;
+
+const char * Warn::names [TYPES] =
+{
+#define W(x, y) y
+ RE2C_WARNING_TYPES
+#undef W
+};
+
+Warn::Warn ()
+ : mask ()
+ , error_accuml (false)
+{
+ for (uint32_t i = 0; i < TYPES; ++i)
+ {
+ mask[i] = SILENT;
+ }
+}
+
+bool Warn::error () const
+{
+ return error_accuml;
+}
+
+void Warn::set (type_t t, option_t o)
+{
+ switch (o)
+ {
+ case W:
+ mask[t] |= WARNING;
+ break;
+ case WNO:
+ mask[t] &= ~WARNING;
+ break;
+ case WERROR:
+ // unlike -Werror, -Werror- implies -W
+ mask[t] |= (WARNING | ERROR);
+ break;
+ case WNOERROR:
+ mask[t] &= ~ERROR;
+ break;
+ }
+}
+
+void Warn::set_all ()
+{
+ for (uint32_t i = 0; i < TYPES; ++i)
+ {
+ mask[i] |= WARNING;
+ }
+}
+
+// -Werror doesn't set any warnings: it only guarantees that if a warning
+// has been set by now or will be set later then it will result into error.
+void Warn::set_all_error ()
+{
+ for (uint32_t i = 0; i < TYPES; ++i)
+ {
+ mask[i] |= ERROR;
+ }
+}
+
+void Warn::fail (type_t t, uint32_t line, const char * s)
+{
+ if (mask[t] & WARNING)
+ {
+ // -Werror has no effect
+ warning (names[t], line, false, "%s", s);
+ }
+}
+
+void Warn::condition_order (uint32_t line)
+{
+ if (mask[CONDITION_ORDER] & WARNING)
+ {
+ const bool e = mask[CONDITION_ORDER] & ERROR;
+ error_accuml |= e;
+ warning (names[CONDITION_ORDER], line, e,
+ "looks like you use hardcoded numbers instead of autogenerated condition names: "
+ "better add '/*!types:re2c*/' directive or '-t, --type-header' option "
+ "and don't rely on fixed condition order.");
+ }
+}
+
+void Warn::empty_class (uint32_t line)
+{
+ if (mask[EMPTY_CHARACTER_CLASS] & WARNING)
+ {
+ const bool e = mask[EMPTY_CHARACTER_CLASS] & ERROR;
+ error_accuml |= e;
+ warning (names[EMPTY_CHARACTER_CLASS], line, e, "empty character class");
+ }
+}
+
+void Warn::match_empty_string (uint32_t line)
+{
+ if (mask[MATCH_EMPTY_STRING] & WARNING)
+ {
+ const bool e = mask[MATCH_EMPTY_STRING] & ERROR;
+ error_accuml |= e;
+ warning (names[MATCH_EMPTY_STRING], line, e, "rule matches empty string");
+ }
+}
+
+void Warn::swapped_range (uint32_t line, uint32_t l, uint32_t u)
+{
+ if (mask[SWAPPED_RANGE] & WARNING)
+ {
+ const bool e = mask[SWAPPED_RANGE] & ERROR;
+ error_accuml |= e;
+ warning (names[SWAPPED_RANGE], line, e, "range lower bound (0x%X) is greater than upper bound (0x%X), swapping", l, u);
+ }
+}
+
+void Warn::undefined_control_flow (uint32_t line, const std::string & cond, std::vector & ways, bool overflow)
+{
+ if (mask[UNDEFINED_CONTROL_FLOW] & WARNING)
+ {
+ const bool e = mask[UNDEFINED_CONTROL_FLOW] & ERROR;
+ error_accuml |= e;
+
+ // report shorter patterns first
+ std::sort (ways.begin (), ways.end (), cmp_ways);
+
+ warning_start (line, e);
+ fprintf (stderr, "control flow %sis undefined for strings that match ", incond (cond).c_str ());
+ const size_t count = ways.size ();
+ if (count == 1)
+ {
+ fprint_way (stderr, ways[0]);
+ }
+ else
+ {
+ for (size_t i = 0; i < count; ++i)
+ {
+ fprintf (stderr, "\n\t");
+ fprint_way (stderr, ways[i]);
+ }
+ fprintf (stderr, "\n");
+ }
+ if (overflow)
+ {
+ fprintf (stderr, " ... and a few more");
+ }
+ fprintf (stderr, ", use default rule '*'");
+ warning_end (names[UNDEFINED_CONTROL_FLOW], e);
+ }
+}
+
+void Warn::unreachable_rule (const std::string & cond, const rule_info_t & rule, const rules_t & rules)
+{
+ if (mask[UNREACHABLE_RULES] & WARNING)
+ {
+ const bool e = mask[UNREACHABLE_RULES] & ERROR;
+ error_accuml |= e;
+ warning_start (rule.line, e);
+ fprintf (stderr, "unreachable rule %s", incond (cond).c_str ());
+ const size_t shadows = rule.shadow.size ();
+ if (shadows > 0)
+ {
+ const char * pl = shadows > 1
+ ? "s"
+ : "";
+ std::set::const_iterator i = rule.shadow.begin ();
+ fprintf (stderr, "(shadowed by rule%s at line%s %u", pl, pl, rules.find (*i)->second.line);
+ for (++i; i != rule.shadow.end (); ++i)
+ {
+ fprintf (stderr, ", %u", rules.find (*i)->second.line);
+ }
+ fprintf (stderr, ")");
+ }
+ warning_end (names[UNREACHABLE_RULES], e);
+ }
+}
+
+void Warn::useless_escape (uint32_t line, uint32_t col, char c)
+{
+ if (mask[USELESS_ESCAPE] & WARNING)
+ {
+ const bool e = mask[USELESS_ESCAPE] & ERROR;
+ error_accuml |= e;
+ warning (names[USELESS_ESCAPE], line, e, "column %u: escape has no effect: '\\%c'", col, c);
+ }
+}
+
+} // namespace re2c
diff --git a/tools/re2c/src/conf/warn.h b/tools/re2c/src/conf/warn.h
new file mode 100644
index 000000000..fb313b01d
--- /dev/null
+++ b/tools/re2c/src/conf/warn.h
@@ -0,0 +1,67 @@
+#ifndef _RE2C_CONF_WARN_
+#define _RE2C_CONF_WARN_
+
+#include "src/util/c99_stdint.h"
+#include
+#include
+
+#include "src/ir/skeleton/way.h"
+#include "src/parse/rules.h"
+
+namespace re2c {
+
+#define RE2C_WARNING_TYPES \
+ W (CONDITION_ORDER, "condition-order"), \
+ W (EMPTY_CHARACTER_CLASS, "empty-character-class"), \
+ W (MATCH_EMPTY_STRING, "match-empty-string"), \
+ W (SWAPPED_RANGE, "swapped-range"), \
+ W (UNDEFINED_CONTROL_FLOW, "undefined-control-flow"), \
+ W (UNREACHABLE_RULES, "unreachable-rules"), \
+ W (USELESS_ESCAPE, "useless-escape"),
+
+class Warn
+{
+public:
+ enum type_t
+ {
+#define W(x, y) x
+ RE2C_WARNING_TYPES
+#undef W
+ TYPES // count
+ };
+ enum option_t
+ {
+ W,
+ WNO,
+ WERROR,
+ WNOERROR
+ };
+
+private:
+ static const uint32_t SILENT;
+ static const uint32_t WARNING;
+ static const uint32_t ERROR;
+ static const char * names [TYPES];
+ uint32_t mask[TYPES];
+ bool error_accuml;
+
+public:
+ Warn ();
+ bool error () const;
+ void set (type_t t, option_t o);
+ void set_all ();
+ void set_all_error ();
+ void fail (type_t t, uint32_t line, const char * s);
+
+ void condition_order (uint32_t line);
+ void empty_class (uint32_t line);
+ void match_empty_string (uint32_t line);
+ void swapped_range (uint32_t line, uint32_t l, uint32_t u);
+ void undefined_control_flow (uint32_t line, const std::string & cond, std::vector & ways, bool overflow);
+ void unreachable_rule (const std::string & cond, const rule_info_t & rule, const rules_t & rules);
+ void useless_escape (uint32_t line, uint32_t col, char c);
+};
+
+} // namespace re2c
+
+#endif // _RE2C_CONF_WARN_
diff --git a/tools/re2c/src/globals.h b/tools/re2c/src/globals.h
new file mode 100644
index 000000000..b2ea67ae0
--- /dev/null
+++ b/tools/re2c/src/globals.h
@@ -0,0 +1,24 @@
+#ifndef _RE2C_GLOBALS_
+#define _RE2C_GLOBALS_
+
+#include
+
+#include "src/conf/opt.h"
+#include "src/conf/warn.h"
+#include "src/util/c99_stdint.h"
+
+namespace re2c
+{
+
+extern bool bUsedYYBitmap;
+extern bool bWroteGetState;
+extern bool bWroteCondCheck;
+extern uint32_t last_fill_index;
+extern std::string yySetupRule;
+
+extern Opt opts;
+extern Warn warn;
+
+} // end namespace re2c
+
+#endif // _RE2C_GLOBALS_
diff --git a/tools/re2c/src/ir/adfa/action.h b/tools/re2c/src/ir/adfa/action.h
new file mode 100644
index 000000000..3fe01ed78
--- /dev/null
+++ b/tools/re2c/src/ir/adfa/action.h
@@ -0,0 +1,109 @@
+#ifndef _RE2C_IR_ADFA_ACTION_
+#define _RE2C_IR_ADFA_ACTION_
+
+#include
+
+#include "src/codegen/label.h"
+#include "src/util/c99_stdint.h"
+#include "src/util/uniq_vector.h"
+
+namespace re2c
+{
+
+struct OutputFile;
+class RuleOp;
+struct State;
+
+struct Initial
+{
+ label_t label;
+ bool setMarker;
+
+ inline Initial (label_t l, bool b)
+ : label (l)
+ , setMarker (b)
+ {}
+};
+
+typedef uniq_vector_t accept_t;
+
+class Action
+{
+public:
+ enum type_t
+ {
+ MATCH,
+ INITIAL,
+ SAVE,
+ MOVE,
+ ACCEPT,
+ RULE
+ } type;
+ union
+ {
+ Initial * initial;
+ uint32_t save;
+ const accept_t * accepts;
+ const RuleOp * rule;
+ } info;
+
+public:
+ inline Action ()
+ : type (MATCH)
+ , info ()
+ {}
+ ~Action ()
+ {
+ clear ();
+ }
+ void set_initial (label_t label, bool used_marker)
+ {
+ clear ();
+ type = INITIAL;
+ info.initial = new Initial (label, used_marker);
+ }
+ void set_save (uint32_t save)
+ {
+ clear ();
+ type = SAVE;
+ info.save = save;
+ }
+ void set_move ()
+ {
+ clear ();
+ type = MOVE;
+ }
+ void set_accept (const accept_t * accepts)
+ {
+ clear ();
+ type = ACCEPT;
+ info.accepts = accepts;
+ }
+ void set_rule (const RuleOp * const rule)
+ {
+ clear ();
+ type = RULE;
+ info.rule = rule;
+ }
+
+private:
+ void clear ()
+ {
+ switch (type)
+ {
+ case INITIAL:
+ delete info.initial;
+ break;
+ case MATCH:
+ case SAVE:
+ case MOVE:
+ case ACCEPT:
+ case RULE:
+ break;
+ }
+ }
+};
+
+} // namespace re2c
+
+#endif // _RE2C_IR_ADFA_ACTION_
diff --git a/tools/re2c/src/ir/adfa/adfa.cc b/tools/re2c/src/ir/adfa/adfa.cc
new file mode 100644
index 000000000..cb41d0351
--- /dev/null
+++ b/tools/re2c/src/ir/adfa/adfa.cc
@@ -0,0 +1,135 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "src/codegen/go.h"
+#include "src/ir/adfa/adfa.h"
+#include "src/ir/dfa/dfa.h"
+#include "src/ir/skeleton/skeleton.h"
+#include "src/util/allocate.h"
+
+namespace re2c
+{
+
+DFA::DFA
+ ( const dfa_t &dfa
+ , const std::vector &fill
+ , Skeleton *skel
+ , const charset_t &charset
+ , const std::string &n
+ , const std::string &c
+ , uint32_t l
+ )
+ : accepts ()
+ , skeleton (skel)
+ , name (n)
+ , cond (c)
+ , line (l)
+ , lbChar(0)
+ , ubChar(charset.back())
+ , nStates(0)
+ , head(NULL)
+
+ // statistics
+ , max_fill (0)
+ , need_backup (false)
+ , need_backupctx (false)
+ , need_accept (false)
+{
+ const size_t nstates = dfa.states.size();
+ const size_t nchars = dfa.nchars;
+
+ State **i2s = new State*[nstates];
+ for (size_t i = 0; i < nstates; ++i)
+ {
+ i2s[i] = new State;
+ }
+
+ State **p = &head;
+ for (size_t i = 0; i < nstates; ++i)
+ {
+ dfa_state_t *t = dfa.states[i];
+ State *s = i2s[i];
+
+ ++nStates;
+ *p = s;
+ p = &s->next;
+
+ s->isPreCtxt = t->ctx;
+ s->rule = t->rule;
+ s->fill = fill[i];
+ s->go.span = allocate(nchars);
+ uint32_t j = 0;
+ for (uint32_t c = 0; c < nchars; ++j)
+ {
+ const size_t to = t->arcs[c];
+ for (;++c < nchars && t->arcs[c] == to;);
+ s->go.span[j].to = to == dfa_t::NIL ? NULL : i2s[to];
+ s->go.span[j].ub = charset[c];
+ }
+ s->go.nSpans = j;
+ }
+ *p = NULL;
+
+ delete[] i2s;
+}
+
+DFA::~DFA()
+{
+ State *s;
+
+ while ((s = head))
+ {
+ head = s->next;
+ delete s;
+ }
+
+ delete skeleton;
+}
+
+void DFA::reorder()
+{
+ std::vector ord;
+ ord.reserve(nStates);
+
+ std::queue todo;
+ todo.push(head);
+
+ std::set done;
+ done.insert(head);
+
+ for(;!todo.empty();)
+ {
+ State *s = todo.front();
+ todo.pop();
+ ord.push_back(s);
+ for(uint32_t i = 0; i < s->go.nSpans; ++i)
+ {
+ State *q = s->go.span[i].to;
+ if(q && done.insert(q).second)
+ {
+ todo.push(q);
+ }
+ }
+ }
+
+ assert(nStates == ord.size());
+
+ ord.push_back(NULL);
+ for(uint32_t i = 0; i < nStates; ++i)
+ {
+ ord[i]->next = ord[i + 1];
+ }
+}
+
+void DFA::addState(State *s, State *next)
+{
+ ++nStates;
+ s->next = next->next;
+ next->next = s;
+}
+
+} // namespace re2c
+
diff --git a/tools/re2c/src/ir/adfa/adfa.h b/tools/re2c/src/ir/adfa/adfa.h
new file mode 100644
index 000000000..95f512d63
--- /dev/null
+++ b/tools/re2c/src/ir/adfa/adfa.h
@@ -0,0 +1,101 @@
+#ifndef _RE2C_IR_ADFA_ADFA_
+#define _RE2C_IR_ADFA_ADFA_
+
+#include
+#include "src/util/c99_stdint.h"
+#include
+#include
+
+#include "src/codegen/go.h"
+#include "src/codegen/label.h"
+#include "src/ir/adfa/action.h"
+#include "src/ir/regexp/regexp.h"
+#include "src/util/forbid_copy.h"
+
+namespace re2c
+{
+
+struct Skeleton;
+struct Output;
+struct OutputFile;
+struct dfa_t;
+
+struct State
+{
+ label_t label;
+ RuleOp * rule;
+ State * next;
+ size_t fill;
+
+ bool isPreCtxt;
+ bool isBase;
+ Go go;
+ Action action;
+
+ State ()
+ : label (label_t::first ())
+ , rule (NULL)
+ , next (0)
+ , fill (0)
+ , isPreCtxt (false)
+ , isBase (false)
+ , go ()
+ , action ()
+ {}
+ ~State ()
+ {
+ operator delete (go.span);
+ }
+
+ FORBID_COPY (State);
+};
+
+class DFA
+{
+ accept_t accepts;
+ Skeleton * skeleton;
+
+public:
+ const std::string name;
+ const std::string cond;
+ const uint32_t line;
+
+ uint32_t lbChar;
+ uint32_t ubChar;
+ uint32_t nStates;
+ State * head;
+
+ // statistics
+ size_t max_fill;
+ bool need_backup;
+ bool need_backupctx;
+ bool need_accept;
+
+public:
+ DFA ( const dfa_t &dfa
+ , const std::vector &fill
+ , Skeleton *skel
+ , const charset_t &charset
+ , const std::string &n
+ , const std::string &c
+ , uint32_t l
+ );
+ ~DFA ();
+ void reorder();
+ void prepare();
+ void calc_stats();
+ void emit (Output &, uint32_t &, bool, bool &);
+
+private:
+ void addState(State*, State *);
+ void split (State *);
+ void findBaseState ();
+ void count_used_labels (std::set & used, label_t prolog, label_t start, bool force_start) const;
+ void emit_body (OutputFile &, uint32_t &, const std::set & used_labels, label_t initial) const;
+
+ FORBID_COPY (DFA);
+};
+
+} // namespace re2c
+
+#endif // _RE2C_IR_ADFA_ADFA_
diff --git a/tools/re2c/src/ir/adfa/prepare.cc b/tools/re2c/src/ir/adfa/prepare.cc
new file mode 100644
index 000000000..39cf65c1b
--- /dev/null
+++ b/tools/re2c/src/ir/adfa/prepare.cc
@@ -0,0 +1,268 @@
+#include "src/util/c99_stdint.h"
+#include
+#include