Compare commits

...
2416 Commits
Author SHA1 Message Date
Ulya Trofimovich 4424a0dd1e CMake: set C++17 standard for benchmarks (required by newer re2). 2023-07-24 08:05:35 +01:00
Ulya Trofimovich 96104a6526 CMakeLists.txt: make C++11 standard required (not optional).
This fixes https://github.com/skvadrik/re2c/issues/455 "Test for C++11
compiler at configure time".
2023-07-21 22:29:45 +01:00
Ulya Trofimovich 59c56044b9 configure.ac: make C++ compiler flag -std=c++11 required (not optional).
This fixes https://github.com/skvadrik/re2c/issues/455 "Test for C++11
compiler at configure time".
2023-07-21 22:15:34 +01:00
Ulya Trofimovich 3841e83f85 Makefile.am: add missing files to distribution.
This fixes https://github.com/skvadrik/re2c/issues/454 "BUILD.md not
present in tarball".
2023-07-21 21:42:54 +01:00
Ulya Trofimovich 7d6641778c BUILD.md: document C++11 requirement.
This fixes https://github.com/skvadrik/re2c/issues/453 "Document C++11
compiler requirement in BUILD.md".
2023-07-21 21:32:51 +01:00
Ulya Trofimovich ece4bb76e3 Release 3.1. 2023-07-19 22:50:22 +01:00
Ulya Trofimovich c3f267b248 release.sh: make the script NixOS-friendly, fix quoting in echo command. 2023-07-19 22:42:25 +01:00
Ulya Trofimovich 60b40d94bd Makefile.lib.am: remove nonexistent header from the list. 2023-07-19 21:47:14 +01:00
Ulya Trofimovich 5abc35226b Update CHANGELOG. 2023-07-18 22:56:45 +01:00
Ulya Trofimovich e868cc58b9 Document configure option --enable-parsers in BUILD.md. 2023-07-13 23:22:55 +01:00
Ulya Trofimovich c633d5de3e Update documentation for capturing and non-capturing groups.
Document the following options:
    --leftomost-captures
    --invert-captures

And the following configurations:
    re2c:leftmost-captures
    re2c:invert-captures

And the new `(! ...)` syntax.
2023-07-13 22:59:47 +01:00
Ulya Trofimovich c86a8bcf5d Add tests for re2c:leftmost-captures and re2c:posix-captures. 2023-07-13 22:27:13 +01:00
Ulya Trofimovich 3a98b54363 Add configuration re2c:leftmost-captures.
It has the same meaning as the --leftmost-captures option.
2023-07-13 22:16:37 +01:00
Ulya Trofimovich 0384cffd9f Fix build scripts for Wine to run on NixOS.
Wine cannot find DLLs by their absolute paths on NixOS, so find and copy
them before running re2c.exe.
2023-07-13 08:06:00 +01:00
Ulya Trofimovich a303a8500d Add missing header include to make src/codegen/code.h self-contained. 2023-07-13 06:22:48 +01:00
Ulya Trofimovich 8c2127d420 Replace enum GorPass with uint32_t as it is used in a bitfield.
It cannot be a `enum class` because it's used in a bitfield and this
triggers compiler warnings and errors on some toolchains (see
https://github.com/skvadrik/re2c/issues/446 for details).

It cannot be a plain `enum` defaulting to `int` as well because of
-Wsigned-enum-bitfield warning (noticed when testing on OpenBSD with
clang-13).
2023-07-12 22:48:57 +01:00
Ulya Trofimovich 54ffc58440 Make function static as it is used in one file. 2023-07-12 22:19:09 +01:00
Ulya Trofimovich 00cbfe90af Drop _POSIX_SOURCE, enable -std=gnu++11 for CMake.
On Unix systems, re2c uses POSIX functions (e.g. fdopen). Certain
systems, such as Cygwin and NetBSD, enable these funtions conditionally
based on certain preprocessor definitions.

Previously https://github.com/skvadrik/re2c/pull/376 fixed the build on
Cygwin by setting _POSIX_SOURCE. However, this broke the build on
FreeBSD which was fixed by commit

This worked for Autotools build system which uses -std=c++11 due to the
use of AC_USE_SYSTEM_EXTENSIONS, but it didn't work for CMake that used
-std=c++11 and disabled extensions with `set(CMAKE_CXX_EXTENSIONS OFF)`.

This commit drops `set(CMAKE_CXX_EXTENSIONS OFF)`, which effectively
enables -std=gnu++11 instead of -std=c++11 for CMake builds. This allows
us to get rid of the problematic _POSIX_SOURCE that breaks the build on
NetBSD.

This was tested on NetBSD-9.3, FreeBSD-13.2 and Cygwin with both
Autotools and CMake.
2023-07-11 23:34:53 +01:00
Ulya Trofimovich bb143b980c libre2c: omit redundant semicolon after namespace.
This gets rid of compiler warnings on some older toolchains (e.g. GCC-10
emits pedantic diagnostic about it, which was fixed in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96068).
2023-07-08 15:02:40 +01:00
Ulya Trofimovich fce87b493f Omit redundant semicolon after namespace.
This gets rid of compiler warnings on some older toolchains (e.g. GCC-10
emits pedantic diagnostic about it, which was fixed in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96068).
2023-07-08 14:17:31 +01:00
Ulya Trofimovich d87f86ed71 Correctly parse raw UTF-8 characters in Flex mode.
With `--flex-syntax` option re2c accepts raw (unquoted) strings.
If `--input-encoding utf8` is also enabled, re2c should parse raw UTF-8
characters in such strings. Previously it failed to do so because the
characters in raw string literals were limited to alphanumeric ASCII and
underscore (those allowed in indentifiers, as in normal mode unquoted
strings would be parsed as identifiers).

This commit fixes it: now in Flex mode and with UTF-8 input, if all
previous rules failed, re2c tries to lex the input as a UTF-8 character.

This fixes bug #447 "Re2go fail when compiling expression containing
combining character".
2023-06-22 07:53:03 +01:00
Ulya Trofimovich d7c697138a Convert GorPass from enum class to plain enum to fix compiler error.
GCC-5.4 is unhappy that `GorPass` which is `enum class: uint32_t` is
stored in a bitfield of size 2 (2 bits). In practice it is safe since
the enum has only three values (0, 1, 2).

Reported in:
  - #445 "make failure for re2c"
  - #446 "make failure for re2c on centos7"
2023-06-18 07:41:04 +01:00
Ulya Trofimovich 580ab173dd run_tests.py: remove exception for overflow-1.re test on Windows.
The test no longer causes stack overflow, so it can now run on Windows
which has a smaller stack than Linux and macOS.
2023-04-27 22:15:20 +01:00
Ulya Trofimovich 6e844850bb run_tests.py: patch backslashes in depfile to fix tests on Windows.
Change file context definition to cover more scenarios that include
filenames, e.g. the case when there is a depfile generated and appended
to the output.
2023-04-27 22:15:20 +01:00
helly25 3205c867bd Provide a min viable http://bazel.build integration.
This allows other projects that use bazel to utilize re2c as a tool.

Limitations:

. Input files (docs, lexer, parser) are not being re-generated.
. No tests are executed.
. Only the main binary is being build as nothing else is needed.

A user will load the package using bazel's 'http_archive' in their
WORKSPACE file.

In their BUILD files they can then use:

```
load("@re2c//bazel:re2c.bzl", "re2c_gen")

re2c_gen(
    name = "file_re2c",
    srcs = ["file.re2c"],
    outs = [
        "file.cc",
        "file.h",
    ]
)

cc_library(
    name = "file_cc",
    srcs = ["file.cc"],
    hdrs = ["file.h"],
)
```

The approach here is to automate as much as possible. In that way, all
source and header files will be found automatically (using glob). Also,
the provided bazel integration is kept to an absolute minimum.

An alternative is to use a `rules_foreign_cc` based approach. But that
would require much more bazel work and knowledge. Plus the result would
end up being a non-hermetic build, thereby bypassing bazel's advantages.
Further, using a rules_foreign_cc approach is much slower (for me ~x10).
2023-04-27 13:22:59 +01:00
Ulya Trofimovich 2dda36aa66 Header file should be a dependency, not a target.
So move it before the colon in the dependency file generated with
--depfile option. This fixes bug #440.
2023-04-26 00:04:33 +01:00
Ulya Trofimovich f807f7636e Add header file to the dependencies generated with --depfile option.
This fixes bug #440 "Generated header file is not present in depfile".
2023-04-25 23:44:14 +01:00
Ulya Trofimovich ce75619557 Add configuration re2c:invert_captures.
Make option --invert-captures configurable. This requires postponing the
decision whether a group is capturing or not to the after-parsing stage
when the configurations for a block are known and the immutable AST is
converted to a regexp.

Add a test for the new configuration.
2023-04-24 23:55:49 +01:00
Ulya Trofimovich dedd72dd66 Add tests for --invert-captures option. 2023-04-24 23:55:49 +01:00
Ulya Trofimovich bf3ff8f3ab Merge AST nodes CAP and REF for capturing and non-capturing groups.
These nodes are similar enough so that it is easier to handle them as
one node with a boolean parameter.
2023-04-21 22:12:40 +01:00
Ulya Trofimovich 20030ff194 Add option --invert-captures.
The new option inverts the meaning on capturing and non-capturing
parentheses: `(! ...)` becomes capturing, and `( ... )` becomes
non-capturing, including the implicit whole-regexp group, which also
becomes non-capturing.

The idea of the new option is to let the user decide which gropus should
be capturing and which are purely structural, and explicitly mark only
the capturing ones for submatch extraction.
2023-04-21 22:10:14 +01:00
Ulya Trofimovich 338806b96c Change syntax for explicit non-capturing groups.
The old syntax was `(? ...)`, the new syntax is `(! ...)`. This is in
preparation to add --invert-captures option that will flip the meaning
of capturing and non-capturing parentheses.
2023-04-19 07:20:42 +01:00
Ulya Trofimovich 6b7a437ab4 GitHub actions: replace set-output command with environment files.
This fixes a warning on GitHub actions workflows: "The `set-output`
command is deprecated and will be disabled soon. Please upgrade to using
Environment Files".
2023-04-11 23:49:06 +01:00
Ulya Trofimovich 8bdc8345cd GitHub actions: update action versions from @v2 to @v3.
This fixes a warning on GitHub actions workflows: "Node.js 12 actions
are deprecated. Please update the following actions to use Node.js 16".
2023-04-11 23:23:36 +01:00
Ulya Trofimovich 0d3eab85be Delete a few tests that are very similar to other tests. 2023-04-11 23:09:27 +01:00
Ulya Trofimovich bb63ccb687 Add tests for the new option --leftmost-captures. 2023-04-11 22:14:35 +01:00
Ulya Trofimovich 1949ed2dec Move and rename tests for capturing groups.
Prepare for adding tests for the new --leftmost-captures option.
2023-04-08 09:18:44 +01:00
Ulya Trofimovich 55de79d8f4 Add option --leftmost-captures.
The new option allows one to use POSIX syntax for capturing groups
with leftmost-greedy disambiguation. This comibination has already
been supported by libre2c, so the changes needed to expose it in re2c
are minimal.
2023-03-25 12:07:17 +00:00
Ulya Trofimovich b813c9b481 Add missing structural parentheses for non-capturing groups.
In the case of POSIX disambiguation (with --posix-captures option) it is
necessary to add structural tags around non-capturing groups, otherwise
disambiguation will be incorrect.

Commit f519385213 that allowed the use of
implicit non-capturing groups didn't properly add structural parentheses
around implicit capturing groups (which are needed if the group contains
nested capturing groups).

Commit 1edd25d31d that added explicit
non-capturing groups repeated the same error, only for the newly added
syntax `(? ...)`.

This resulted in `(? "a"* | ("aa"))*` being parsed incorrectly, as if
leftmost greedy disambiguation was used instead of POSIX disambiguation,
giving priority to the shorter first alternative `"a"` rather than the
longer match `"aa"` as POSIX requires.

This commit ensures correctness for both explicit and implicit
non-capturing groups by adding proper structural tags for the case of
AST sub-node `REF`. It is expected that it will bring back some of the
overhead on POSIX disambiguation reduced by the introduction of
non-capturing groups.

Related bugs: #438, #308.
2023-03-25 10:23:05 +00:00
Ulya Trofimovich 156a947bb3 Rename a few tests.
Rename tests for implicit non-capturing groups so that they are named
similar to the tests for explicit non-capturing groups, and thus easier
to locate and compare.
2023-03-25 08:09:49 +00:00
Ulya Trofimovich 764f4e2de2 Remove unused name field in the AST sub-node REF.
This sub-ode is used for named definitions and non-capturing groups. The
latter do not have a name (previously a dummy name "<group>" was given
to such groups, but it turned out that the name is unused anyway).
2023-03-25 08:03:25 +00:00
Ulya Trofimovich 1edd25d31d Add explicit non-capturing groups.
This is useful in POSIX mode (with --posix-captures option) in order to
avoid unnecessary captures and reduce the amount of tags.

The new syntax for non-capturing groups is `(? ...)`.

Add tests for the new feature. Note that test results coincide with the
corresponding test for implicit groups (where the same group is not
parenthesized at all, but implicit grouping is achieved with the help
of a named definition).

This addresses bugs #438 "POSIX captures processing" and #308
"Overloading precedence marker (e.g. (pattern)) with 'posix' group
markers (also parenthesis) causes loss of full functionality".
2023-03-24 23:45:58 +00:00
Ulya Trofimovich f519385213 Allow implicit grouping with --posix-captures.
Allow the use of named definitions that cause implicit grouping and
circumvent the absence of syntax for non-capturing groups. This is not
allowed by the POSIX standard, but this feature is useful in practice
and many regexp engines support it.

Update the tests that should no longer result into a compilation error.

This addresses bugs #438 "POSIX captures processing" and #308
"Overloading precedence marker (e.g. (pattern)) with 'posix' group
markers (also parenthesis) causes loss of full functionality".
2023-03-24 22:43:48 +00:00
Ulya Trofimovich 8bae0b0557 Extend tests for implicit grouping with --posix-captures. 2023-03-24 22:36:38 +00:00
helly25 d28e5063d1 Fix warning for switch statement for all compilers by providing all enum values. 2023-03-23 17:17:55 +00:00
helly25 91ace6a10e Fix some build warnings. 2023-03-23 12:13:09 +00:00
helly25 d1250a2cd8 Fix documentation "@@(...}" -> "@@{...}". 2023-03-23 12:13:09 +00:00
Ulya Trofimovich 742ff817ac Revert "Introduce Dlang codegen."
This reverts commit 8df0ed6737.

Reason for revert: D backend is not ready yet: there are no examples
and tests, the work on it has stopped. In the future support for D and
other languages should be added in a generic way via language syntax
files, rather than modifying re2c codegen to support each new language.
2023-03-19 22:40:47 +00:00
Ulya Trofimovich 8a0d0a0470 Sort definitions in unicode_categories.txt 2023-03-19 22:38:31 +00:00
Alex Grant Benedict 8df0ed6737 Introduce Dlang codegen.
Dlang supports both case ranges and the pointer API so there are a few changes
related to the error messages in options/opt.cc. The Golang backend has some
test cases that are expected to fail and check for an exact error string.

The syntax of Dlang is very close to that of C. However, there are a few
differences which impact codegen. Case ranges in D are done by
`case ${1}: .. case ${2}:` and there is no implicit fallthrough, so we need a
`goto case` at the end of cases with fallthrough. Also Dlang uses `enum`s for
most compile-time constants, which is similar to C's define macro. Lastly, in
D `char` is unsigned.

Because of the similarities between C and D, we now have some fallthrough
cases to handle both C and D.

References:

https://dlang.org/spec/statement.html#switch-statement
https://dlang.org/spec/statement.html#no-implicit-fallthrough
https://dlang.org/spec/type.html#pointers
https://dlang.org/spec/expression.html#pointer_arithmetic
https://dlang.org/spec/type.html#basic-data-types
2023-01-12 20:19:30 +00:00
Ulya Trofimovich 8196567dac Merge compile.cc into main.cc, get rid of header file compile.h. 2022-11-24 08:55:42 +00:00
Ulya Trofimovich 838398c918 Allocate AST parts which have longer lifetime with the output allocator.
Previosuly they were allocated using AST allocator, which made it
necessary to keep AST memory until the main codegen pass. Now it is
possible to release AST memory after parsing.
2022-11-24 07:45:24 +00:00
Ulya Trofimovich 86cb51e35b Explicitly deallocate memory used for AST. 2022-11-22 23:51:00 +00:00
Ulya Trofimovich 78b84cffdc Check that rendering pass did not generate any unexpected warnings. 2022-11-22 07:47:58 +00:00
Ulya Trofimovich fba7da441a Clean up the way codegen passes are called.
Move loops over output blocks into files that handle each pass.
2022-11-20 17:20:45 +00:00
Ulya Trofimovich 1330e01c34 Get rid of CodegenCtxGlobal. 2022-11-19 13:13:25 +00:00
Ulya Trofimovich 95102ca491 Rename codegen passes, slightly restructure fixup and render passes. 2022-11-18 21:39:02 +00:00
Ulya Trofimovich b8ce97337b Rename codegen files and move code from one file to another. 2022-11-17 22:28:30 +00:00
Ulya Trofimovich b90bcd0a8a Release memory used for DFAs after the main codegen phase. 2022-11-16 23:10:01 +00:00
Ulya Trofimovich 0799d52bfa Get rid of unused codegen context and remove it from the "combine" pass. 2022-11-16 22:20:15 +00:00
Ulya Trofimovich 128c8bf82f Get rid of lat codegen pass that removed empty statements.
This pass is no longer needed after commit
bdbcb1f490 that stopped generating empty
stubs for line directives in Rust.
2022-11-16 22:07:25 +00:00
Ulya Trofimovich e4029874d9 Remove useless late codegen pass.
This pass is no longer needed, as all the transformations have been
moved to other passes.
2022-11-16 21:59:36 +00:00
Ulya Trofimovich bdbcb1f490 Don't generate useless line directive stubs in Rust mode.
Rust does not support line directives. Previosuly re2c generated stubs
that were replaced with empty statements and later removed by a follow
up codegen pass. Now the stubs are not generated at all in Rust mode.
2022-11-16 21:52:01 +00:00
Ulya Trofimovich 5ef4253b80 Move label generation from late codegen to rendering phase.
Labels cannot be generated during main codegen phase: codegen for state
dispatch may add more use cases for block start labels. These labels may
come from blocks either before or after state dispatch that uses them,
which makes it difficult to decide in advance (especially since state
dispatch itself cannot be expanded before the main codegen phase).
Therefore label generation has to be delayed. However, there is no need
for a separate codegen pass, as it can be done by the rendering pass.
2022-11-15 22:50:00 +00:00
Ulya Trofimovich 8f9c605bf6 Get rid of the first delayed codegen pass.
All the functionality has moved to the main codegen pass, as it no
longer needs to be delayed. Second delayed pass still remains: it
expands labels and removes line directives for rust.
2022-11-14 22:43:49 +00:00
Ulya Trofimovich 1af943dce9 Move max:re2c/maxnmatch:re2c expansion to the main codegen phase. 2022-11-14 22:19:40 +00:00
Ulya Trofimovich 9b5bb250c5 Move condition dispatch generation to the main codegen phase. 2022-11-14 22:11:58 +00:00
Ulya Trofimovich 0be4f88adc Move yych/yyaccept/yystate generation to the main codegen phase. 2022-11-14 21:55:29 +00:00
Ulya Trofimovich 2ce67726cc Move condition dispatch generation to the main codegen phase.
It no longer needs to be delayed until late codegen phase, and there is
no need for a special code kind: it can be generated during the main
codegen phase.
2022-11-14 08:02:40 +00:00
Ulya Trofimovich c09efc1635 Move condition enum generation to the main codegen phase.
It no longer needs to be delayed until late codegen phase (all blocks
are parsed before the main codegen phase, and the list of conditions is
known by that time).
2022-11-14 07:33:11 +00:00
Ulya Trofimovich 5633e79453 Move stags:re2c and mtags:re2c expansion to the main codegen phase.
It no longer needs to be delayed until late codegen phase, since all
blocks are parsed before the main codegen phase now.
2022-11-13 21:49:47 +00:00
Ulya Trofimovich 78bd2e39da Move state dispatch generation to the main codegen phase.
It no longer needs to be delayed until late codegen phase.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 5356f2e2da Always generate YYGETSTATE inside of YYLESSTHAN check.
YYGETSTATE is only needed in the YYFILL call, it doesn't matter in case
YYLESSTHAN check fails and YYFILL is not called at all. The value of
state variable cannot "leak" into semantic action, as it is reset to -1
immediateluy before executing the action.

Previosuly YYGETSTATE was generated inside of the YYLESSTHAN check if
the end-of-input rule $ was used, but outside if it wasn't used. This
commit unifies the behavior.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich d676b6b3e0 Decouple storable state dispatch generation from the main codegen pass. 2022-11-13 16:53:34 +00:00
Ulya Trofimovich c180dfc33b Allocate fill labels in advance before the main codegen pass.
Previously they were allocated during codegen, which implied that
state dispatch in storable state mode had to be generated in the late
codegen phase (because fill labels are used in transitions for state
dispatch).
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 89fa4604d3 Decouple logic for state goto for use blocks and normal blocks.
Use blocks should generate state goto even if it has previously been
generated. However, that should not affect normal blocks (and previosuly
it did, as the global boolean flags was reset when seeing a use block).
2022-11-13 16:53:34 +00:00
Ulya Trofimovich e4f4fac798 Split early codegen into first and second pass.
This is so that we can gather whole-program information during the
first pass and use it during the second pass (obliviating the need for
late codegen).
2022-11-13 16:53:34 +00:00
Ulya Trofimovich b605cfa3b6 Set initial state action together with other actions.
Move it from codegen to where it belongs.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 71bded8e06 Get rid of OutputFragment, rename a few methods.
The only advantage of `OutputFragment` compared to just `CodeList` was
that it additionally stored indentation level. However, it turns out
that just using top indent in all fragments produces the same output
(some of the fragments are line directives that always use zero indent).
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 85ea9a0e7a Separate parsing and codegen phases.
Previously parsing and early codegen were intermixed: early codegen for
each block was done before parsing for the next block started. This is
problematic, because it creates the need for a late codegen phase that
expands whole-program constructs such as state goto or condition enum.
And then an extra pass is needed to generate labels. Used-label analysis
is spread throughout all phases: some of it is needed before early
codegen (so that we know which goto transitions can be elided and avoid
generating redundant loop/switch cases, and also to decide the need for
backup statement if there is a loop through initial state). But some of
the used-label analysis happens during the late codegen phase (expansion
of state goto may add new uses for start labels).

Separating parsing and codegen will let us simplify codegen, get rid of
the late phase and make used-label analysis and label enumeration more
clean and compact.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 1817809309 Split codegen for skeleton / dot / code targets into separate functions. 2022-11-13 16:53:34 +00:00
Ulya Trofimovich 6ba82b4c80 Set correct default value for top indent with skeleton.
Default value should be 0. Previously defult value was 2 (for some
reason), and value 0 was set at runtime.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 77714fce94 Always wrap the generated code in braces.
Previously this was done only if there were declarations of local
variables. However, the cases when braces can be omitted are rare, and
detecting them makes the code more complex for very little value.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 79215e3bdd Separate loop/switch and label/goto branches in codegen.
They are too dissimilar.
2022-11-13 16:53:34 +00:00
Ulya Trofimovich 22cb071cb2 Simplify generation of start label and dispatch to start conditions.
Start label is only needed for the first DFA in a block: although it was
previously attributed to a DFA, it should be attributed to the whole
block. Autogenerated start label is used by state dispatch in storable
state mode. It is generated before condition dispatch, which is also
generated once per block.

This patch moves start label and condition dispatch generation out of
the per-DFA codegen loop and makes it explicit that they are generated
once per block.
2022-11-13 16:53:34 +00:00
Doug Cook (WINDOWS) 374b5ecc84 BUILD.md - update dependencies, info about cmake presets
- In addition to a C++ compiler, Windows builds require a build system
  (CMake or bash). Clarify the dependencies to say this.
- Python 3 is required for tests, and tests should always be available,
  and both CMake and Automake give a hard error for missing Python 3,
  so just say Python 3 is required.
- Update docs rebuild dependencies to specify Python3 and Docutils,
  since that is what you need to install to make rst2man available.
- Add an explanation of how to use the CMake presets since they're pretty
  good.
- A few other minor corrections.
2022-11-07 21:13:22 +00:00
Doug Cook (WINDOWS) 3a10633b8c Remove unused .sh scripts 2022-11-07 08:10:30 +00:00
Doug Cook (WINDOWS) fcdca1f411 Autotools - use rst2txt for docs
- Prequisite check for Python3 docutils module instead of rst2man.
- Use `split_man.py` instead of `split_man.sh`.
- Use `rst2txt.py` instead of `rst2man` + `gen_help.sh`.
- Explicitly use `$(PYTHON) <scriptname>` when calling python scripts.
2022-11-07 08:10:30 +00:00
Ulya Trofimovich e3ec259703 Regenerate Unicode tests and include header to support a newer standard.
Regenerate files using haskell script test/encodings/unicode_groups.hs
that is based on Data.Charset library (charser-0.3.9 package). The
script generates tests in test/unicode directory inplace and include
file unicode_categories.re.inc that needs to be copied to
include/unicode_categories.re.

Update test results. As there are substantial changes in the standard,
updates are also nontrivial. They have been verified with
test/__run_unicode_tests.sh.

The three examples for C, Rust and Go were werified with __run_all.sh
scripts in examples/{c,go,rust) respectively.
2022-11-04 08:02:02 +00:00
Ulya Trofimovich f006e75513 Add missing header include.
This fixes issue #424 "Failed to build master branch on Cygwin/MSYS2
fails".
2022-11-01 22:01:59 +00:00
Doug Cook (WINDOWS) 34753db06e Fix repository CRLF on Windows 2022-10-25 07:41:42 +01:00
Doug Cook (WINDOWS) 130efff19c Enable CMake re2rust.1, update bootstrap docs 2022-10-25 07:41:42 +01:00
Doug Cook (WINDOWS) d4ba85be51 CMake - Windows-compatible doc bootstrapping
Pretty much every Python install includes Docutils, and Docutils is 95%
of what is needed to bootstrap docs on Windows. Fill in the rest.

- `docutils_txt.py` is a Docutils text-output Writer class with support for
  writing a C file.
- `rst2man.py` is a wrapper for Docutils converting to MAN file. (Copied
  from Docutils repo.)
- `rst2txt.py` is a wrapper for Docutils converting to TXT file. (Same
  as rst2man.py but it uses docutils_txt as the Writer.)
- `split_man.py` is a Python implementation of `split_man.sh`.
- Change CMake build to use the new scripts.

Additional changes:

- CMakeLists: give error message if docutils module not found.
- ci-cmake: Give hint about where to find Python3 so that the private
  install is preferred over the system install. Enable docs regen for
  Windows.
2022-10-25 07:41:42 +01:00
Sergei Trofimovich 7adf8372f6 src/util/check.h: always use DCHECK(x) argument to avoid warnings
Without the change on `gcc-13` build warns as:

    ./src/parse/input.h: In member function 're2c::loc_t re2c::Input::cur_loc() const':
    ./src/parse/input.h:139:20: warning: unused variable 'p' [-Wunused-variable]
      139 |     const uint8_t* p = cur;
          |                    ^

The change turns `DCHECK(x)` into a statement that uses `x`.
2022-10-22 17:28:34 +01:00
Ulya Trofimovich c40ebdb37f Output user-defined start label before the autogenerated one.
User-defined start label is generated once per block, and autogenerated
labels are generated once per each start condition.
2022-10-07 23:35:06 +01:00
Ulya Trofimovich 35913e09e8 Append condition to bitmap name, define all bitmaps at block start.
Previously if start conditions were used, bitmap definitions were
generated at the start of each condition, as they all had the same name
(`yybm` or a user-defined one). This was problematic in storable state
mode, as transitions to `YYFILL` labels bypassed bitmap declaration
(state dispatch is always at the beginning of a block).

Now we use condition-specific names for bitmaps (`yybm` plus underscore
and condition name), so they can all be defined together before state
dispatch, as it happens in blocks that do not use start conditions.
2022-10-07 07:41:07 +01:00
Ulya Trofimovich dff7d0475b Slightly simplify codegen logic that decides if outer braces are needed. 2022-10-06 22:39:44 +01:00
Ulya Trofimovich 6cf371a5b7 Don't generate redundant newline with --storable-state option. 2022-10-05 23:06:03 +01:00
Ulya Trofimovich 4a63376a2f Move code that is specific to the first iteration out of loop. 2022-10-05 22:52:54 +01:00
Ulya Trofimovich 0365d2b03c Move codegen structs into a separate header file. 2022-10-04 07:23:13 +01:00
Ulya Trofimovich a0f1f7f77a Move prolog/epilog generation to separate methods in the Output class. 2022-10-01 20:25:36 +01:00
Ulya Trofimovich f7abcf9864 Rename a few lexer-related classes and functions. 2022-10-01 13:17:22 +01:00
Ulya Trofimovich 0ac0cc5026 Fix -Wmismatched-tags warning. 2022-09-30 07:35:58 +01:00
Ulya Trofimovich 08950f9701 Fix -Wconditional-uninitialized warning. 2022-09-30 07:25:33 +01:00
Ulya Trofimovich ebf0b776e6 Provide wrappers for error reporting functions in the lexer. 2022-09-29 23:32:11 +01:00
Ulya Trofimovich f811c7c6a8 Handle potential strftime errors. 2022-09-29 22:09:13 +01:00
Ulya Trofimovich e988f0ba2b Merge scanner.{h,cc} into input.{h,cc}.
Both pairs of files contain lexer-related declarations and definitions,
the headers are usually included together, and the input.{h,cc} files
are very small.
2022-09-28 07:34:54 +01:00
Ulya Trofimovich dd13fe22af Rename a few AST-related structs, add more comments.
In particular, use term "grammar" rather than "specification".
2022-09-25 07:45:40 +01:00
Ulya Trofimovich ff0e44d9ad Give more precise error (with location) on unexpected end of input.
Also, simplify the logic that prevents parser from reporting a generic
"syntax error" after lexer has already reported a more precise one.
2022-09-24 21:06:13 +01:00
Ulya Trofimovich 51cd34470d Rework the way parameters are passed to the parser.
Do not use a struct, instead pass individual parameters. They are often
used in semantic actions, and addressing them as struct fields adds too
much noise in the source code.
2022-09-24 21:00:21 +01:00
Ulya Trofimovich 7f9e6a78d2 Merge ast.{h,cc} and parse.{h,cc} as both pairs contain AST decls/defs. 2022-09-24 13:04:48 +01:00
Ulya Trofimovich 96ab1a35a7 Renamed a couple of files. 2022-09-22 00:08:45 +01:00
Ulya Trofimovich a5a1a89128 Rename RE structure to Regexp (cosmetic). 2022-09-18 07:43:15 +01:00
Ulya Trofimovich 47f1979115 Move a few functions and remove empty header. 2022-09-18 07:43:15 +01:00
Ulya Trofimovich bb3aa1a14b Remove space before opening parenthesis (cosmetic). 2022-09-18 07:43:15 +01:00
Ulya Trofimovich 6d2611d475 Rename identifiers in camelCase to snake_case (cosmetic). 2022-09-18 07:43:15 +01:00
Ulya Trofimovich c5bc8667e9 Rename DFA to Adfa to reflect that it is "action DFA" (cosmetic). 2022-09-18 07:43:15 +01:00
Ulya Trofimovich 0b15b1eeb0 Reorder options in source file: group them by name (cosmetic). 2022-09-18 07:43:15 +01:00
Ulya Trofimovich 8b8409dd31 Rename options (no API changes, just the names in the source code). 2022-09-18 07:43:15 +01:00
Ulya Trofimovich a6d0e75d96 Rename determinization context fields (get rid of "dc_" prefix).
Prefix was used inconsistently, and other structs/classes don't do it.
2022-09-18 07:33:16 +01:00
Ulya Trofimovich 511a030c0c libre2c: remove GTOP shortest path finding algorithm.
It performs almost identical to GOR1 (sometimes slightly better or
worse), but it has no proven worst-case bound.

Apparently both the updated test and benchmark erroneously flipped GOR1
and GTOP (but the results were so close it didn't matter).
2022-09-18 07:33:13 +01:00
Ulya Trofimovich aa97b01494 libre2c: remove Kuklewicz POSIX disambiguation algorithm.
Previous studies and benchmarks have shown that it is suboptimal, and
an adaptation of Okui-Suzuki algorithm for TNFA is faster.
2022-09-18 07:31:53 +01:00
Ulya Trofimovich 27256be1ed libre2c: remove incorrect backward-matching algorithm.
It was interesting for experimental/benchmarking purposes, but now it is
no longer needed and can be removed.
2022-09-18 07:31:53 +01:00
Sergei Trofimovich 508de1570c bison parsers: mark static yylex() and yyerror()
Unused exported symbols are detected by uselex:

    yyerror: [R]: exported from: src/parse/re2go-parser.o src/parse/parser.o src/parse/re2rust-parser.o
    yylex: [R]: exported from: src/parse/re2go-parser.o src/parse/parser.o src/parse/re2rust-parser.o
2022-09-04 08:00:53 +01:00
Sergei Trofimovich 8161d996f0 bison parsers: switch to pure bison API
Before the change parsers relied on `YYSTYPE` global variable.
Not very handy for libre2c if it's expected to be used in reentrant
or multi-threaded contexts.

The change enables `%define api.pure full` and adjusts lexer calls
to explicitly pass through `YYSTYPE` around.

`%define api.pure full` is preferred to `%pure-parser` (deprecated in
2008, around Bison 2.3b). Should be safe to use.
2022-09-03 20:17:15 +01:00
Sergei Trofimovich efa2ab027b build system: disable timestamp generation for bootstrap files
Eases diff inspection on lexer changes.

While at it dropped deprecated '-r' option.
2022-09-03 19:15:02 +01:00
Sergei Trofimovich 87cf19bf58 cmake/Re2cBootstrapParser.cmake: change flag order to match Makefile.am
Autotools-based and cmake-based build systems had slightly different flag order:

    Makefile.am:    $(AM_V_GEN)$(BISON) --warnings --output=$@ --defines=$(@:cc=h) $<

Let's make them identical.
2022-09-03 18:44:54 +01:00
Sergei Trofimovich 7e7c4b97af src/parse/parser.ypp: use %empty token for empty rule
New `bison --warnings` gives the following helpful diagnostic:

      GEN      src/parse/parser.cc
    src/parse/parser.ypp:60.2: warning: empty rule without %empty [-Wempty-rule]
       60 | : /* empty */
          |  ^
          |  %empty

%empty was introduced in bison-2.7.90 around 2013.
2022-09-03 18:09:14 +01:00
Sergei Trofimovich 67a58414ce build system: enable --warnings for bison
The change allows catching fresh bison diagnostics. Current example:

      GEN      src/parse/parser.cc
    src/parse/parser.ypp:60.2: warning: empty rule without %empty [-Wempty-rule]
       60 | : /* empty */
          |  ^
          |  %empty

The warning itself will be fixed in another change.
2022-09-03 18:09:14 +01:00
Sergei Trofimovich c18aed9f21 .github/workflows/ci-autotools.yml: use latest bison from brew 2022-09-03 18:09:14 +01:00
Ulya Trofimovich 111ee5da7b GitHub Actions: limit stack for tests to 256K.
Run tests as:
    bash -c "ulimit -s 256; make check -j$(nproc)"

I also verified that the tests fail on CI without commit
460412913771e9b7b9506bc623470195f6ccf21e (the last change that was
needed to fix #219).
2022-07-25 08:35:51 +01:00
Ulya Trofimovich 5fffb18701 Rewrite recursion into iteration for rule liveness analysis.
This fixes bug #219. Tested as follows (all tests passed):

    bash -c "ulimit -s 256; time ./run_tests.py"

Original test that revealed the problematic recursive functions:

    bash -c "ulimit -s 256; echo run | gdb --args ./re2c overflow-1.re"
2022-07-25 08:35:51 +01:00
Ulya Trofimovich 02e5d79784 Rewrite recursion into iteration for AST to range conversion.
This partially addresses bug #219.
2022-07-24 16:28:25 +01:00
Ulya Trofimovich a8bf479067 Avoid repeated computation of "has captures" property for AST subtrees.
Save this information in each subtree and compute it bottom-up on AST
construction. This means a slight constant overhead on construction for
non-POSIX case (where this information is unused), but it eliminates a
worst-case quadratic algorithm for the POSIX case (where the property
was recomputed for each alternative/concatenation subexpression).

Note that tags were counted as captures by the old implementation, but
not by the new one, as POSIX regexps cannot have standalone tags.
2022-07-24 16:28:25 +01:00
Ulya Trofimovich 72a304cc28 Add outer decls for static constexpr data members (required by C++11).
In C++17 this is no longer necessary (it makes static constexpr data
members implicitly inline).
2022-07-24 16:28:25 +01:00
Ulya Trofimovich aaf6829263 Rewrite AST to RE conversion using iteration instead of recursion.
This partially addresses bug #219.
2022-07-24 16:28:25 +01:00
Ulya Trofimovich 9724f16b93 Reorder functions (to avoid declaring prototypes at the top of file). 2022-07-24 16:28:25 +01:00
Ulya Trofimovich 6bf6a5896b Rename files (related to multi-pass TDFA). 2022-07-24 16:28:25 +01:00
Ulya Trofimovich 643d387133 Rename (some) structs to follow uniform type naming rules.
Lowercase type names prefixed with `_t` are used for containers and
utility structures. Domain-specific types use camel case.

Also, rename REG_REGLESS to REG_MULTIPASS (but keep the old constant
definition for compatibility).
2022-07-24 16:28:25 +01:00
Ulya Trofimovich 4191b0a54f Slightly restructure TNFA state fields. 2022-07-24 16:28:25 +01:00
Ulya Trofimovich 46a9b4c46e Rewrite TNFA construction using iterative approach instead of recursion.
This partially addresses bug #219.
2022-07-24 16:28:25 +01:00
Ulya Trofimovich bc3a1c2770 Use unsigned character type in the lexers, enable -Wold-style-cast.
Previously we used signed characters and `re2c:yych_conversion = 1;` to
convert from char to uint8_t in the generated lexer code (the lexer
compares `yych` to various literals which may be outside of the signed
ASCII range, depending on the lexical grammar). As a consequence,
-Wold-style-cast was disabled.

Unfortunately now we have to disable -Wreserved-identifiers, as it warns
about user-defined literal suffixes like `_u8` that must start with an
underscore (the standard reserves non-underscore prefix for the future).
2022-07-07 09:03:29 +01:00
Ulya Trofimovich 89a467908c Disable -Wc++98-compat-pedantic with -Weverything (as re2c uses C++11). 2022-07-07 08:57:40 +01:00
Ulya Trofimovich 7e00ea55ae Enable -Wglobal-constructors (with -Weverything). 2022-07-06 23:24:21 +01:00
Ulya Trofimovich 6264787bb1 Add static_cast to fix warning on platforms with 32-bit long. 2022-07-06 22:08:46 +01:00
Ulya Trofimovich f199f3a915 GitHub Actions (CMake): build with -j$(nproc). 2022-07-06 07:45:29 +01:00
Ulya Trofimovich 1f01ceb32b GitHub Actions (Autotools): add nproc on macOS (from coreutils). 2022-07-06 07:27:40 +01:00
Ulya Trofimovich 8e1f7c7c8b Reduce the number of different allocators, make them safer to use.
Use four basic allocator types (defined as different structs, so not
possible to mix with each other by accident):

    - AST allocator (may be shared between blocks)
    - IR allocator (intermediate representations for a single DFA)
    - DFA allocator (codegen for all DFA in a block)
    - output allocator
2022-07-05 23:53:49 +01:00
Ulya Trofimovich a53062c159 CMake: use /W3 not /Wall for MSVC.
Even /W4 emits too much (informational warnings that we are not going to
fix), and /Wall is /W4 plus some warnings that are off by default. See
https://docs.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level

Also disable some selected warnings that add to much noise (C4068 that
complains about unused pragmas and C4996 that complains about functions
like `fopen`).
2022-07-05 23:53:49 +01:00
Ulya Trofimovich 5574e40171 CMake: exclude -Wc++98-compat from -Weverything.
re2c uses C++11, not C++98.
2022-07-05 23:53:49 +01:00
Ulya Trofimovich 2f28225b88 Ignore -Wunused-macros warning for a platform-specific macro. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich 12fe914395 Ignore -Wunused-macros warnings in Bison-generated code.
Previously some of the warnings have been disabled with pragmas, but not
all warnings can be fixed this way, as some of the macros are emitted
too early (before the pragmas).

The fix is to "use" the macros in trivial `#ifndef` clauses.
2022-07-05 23:53:49 +01:00
Ulya Trofimovich 6aee0f1076 Explicitly handle enum values in switch to fix -Wswitch-enum warning. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich ae8b9b179b Remove useless default clause reported by -Wcovered-switch-default. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich 08797d4a89 Remove unused variables reported by -Wunused-variable. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich c3995c3edb Remove unused function templates reported by -Wunused-template. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich a0d8aa952c Remove useless comparison reported by -Wtautological-type-limit-compare. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich fec2a6c808 Rename variables to fix -Wshadow warning. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich ae67b2c98a Initialize variable to fix -Wconditional-uninitialized warning. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich f7095954bd Remove unused macro. 2022-07-05 23:53:49 +01:00
Ulya Trofimovich 2b34974da4 Use printf modifiers %z and %t for size_t and ptrdiff_t.
They were added in C99, so should be available in C++11.

For int64_t / uint64_t use PRId64 / PRIu64 macros from <cinttypes>.

Also fix some formatting issues.
2022-07-05 23:53:49 +01:00
Sergei Trofimovich 243083b29b autogen.sh: drop dangerous 'git clean -dfx' command
Now it's just a one-liner autoreconf.
2022-07-05 23:44:22 +01:00
Sergei Trofimovich 19595aee4d .github/workflows: add basic autotools workflow 2022-07-05 23:30:17 +01:00
Sergei Trofimovich dc1adfaa9a configure.ac: remove redundant escapes 2022-07-05 07:04:33 +01:00
Sergei Trofimovich 0fcb43a7ae .github/workflows: rename ci.yml to ci-cmake.yml
A prerequisite for basic autotools-based build.
2022-07-05 07:04:20 +01:00
Ulya Trofimovich 51c3d5f5ac Replace standard assert with custom CHECK that ignores NDEBUG.
Assertions are used in tests and elsewhere to verify assumptions that
must be correct, or else the program should abort. Compiling them away
in release mode is dangerous. For debug-mode assertions we use `DCHECK`.
2022-07-03 09:24:37 +01:00
Ulya Trofimovich badb1524a7 Fix NDEBUG-mode compiler warning about unused function parameter.
The parameter was used only in `assert`, so there was no warning in
NDEBUG mode.
2022-07-02 19:39:20 +01:00
Ulya Trofimovich f2d85745cc GitHub Actions: run Valgrind tests on CI. 2022-07-02 19:12:30 +01:00
Ulya Trofimovich 8097795340 Fix memory leaks.
A previous fix of error handling revealed memory leaks caused by not
destructing common data structures like tags, rules and charset that
live through different intermediate representations and move from one to
another (regexp -> TNFA -> determinization context -> TDFA -> ADFA).

Previously they were stored as references, and the last IR (ADFA) took
the responsibility for destroying them. This works with normal control
flow, but if there is an error in one of the previous IRs, the program
exits without constructing and (what matters here) destructing ADFA.

The fix is to use move semantics introduced in C++11: instead of storing
references, store values and move common data structures from one IR to
another. This way they are always owned and destroyed by the same IR
that causes the error.

This patch makes all tests pass under valgrind:

  $ ./run_tests.py --valgrind

  $ LD_LIBRARY_PATH=.libs \
    G_SLICE=always-malloc \
    G_DEBUG=gc-friendly \
    GLIBCXX_FORCE_NEW=1 \
      valgrind \
        --track-origins=yes \
        --trace-children=yes \
        --num-callers=50 \
        --track-fds=yes \
        --leak-check=full \
        --show-reachable=yes \
        --malloc-fill=0xa1 \
        --free-fill=0xa1 \
        --suppressions="$HOME/misc/valgrind/all.supp" \
      .libs/test_libre2c
2022-07-02 18:13:23 +01:00
Ulya Trofimovich 3a9b98a0c7 Use std::vector instead of std::valarray for rules.
A long time ago `std::valarray` was used because it did not require copy
semantics for rules. But this depends on the libstdc++ implementation
(if I remember correctly, macOS implementation required copy semantics).
2022-07-02 16:25:39 +01:00
Ulya Trofimovich ff408ec4ce Add proper error handling.
Instead of doing `exit(1)` after printing an error message, return
error code to the calling function and propagate it all the way back to
`main`. Avoid boilerplate and bloating the code with checks by using
consistent error codes throughout the codebase and wrapping function
calls in a `CHECK_RET` macro. Use another macro `RET_FAIL` for errors.

This change has reduced the number of failing tests under valgrind from
131 to 32 (previously all the tests that report an error failed, because
`exit(1)` bypassed the destructors and didn't free memory).
2022-06-29 23:56:43 +01:00
Ulya Trofimovich 43a1a08732 CMake: ensure autogenerated headers are built before included.
In CMake this is done by adding autogenerated sources to an "object
library", which is not really a library, but just a collection of files
that can be used as a library in the sense that other targets can depend
on it. The dependency can be achieved by either adding it explicitly to
another library with something like `target_link_libraries`, or by
adding the object library to the list of source files.

For libre2c the latter was done slightly differently (and incorrectly):
instead of listing object libraries in the list of sources, normal
sources were added to another object library, and the object libraries
for autogenerated and normal sources were listed as sibling entries on
the sources list. So there was no dependency from the object library for
normal sources on the object library for autogenerated sources.

This caused build errors when a normal source file included an
autogenerated header, which was not generated yet. The fix is to not use
object library for normal sources.
2022-06-29 23:56:43 +01:00
Ulya Trofimovich 81c37adbab Optimize the way lexer and parser allocate intermediate values.
For some allocations, move them to slab allocators. For others, replace
them with temporary buffers. Avoid allocating and freeing temporary
values with `new`/`delete`, which was previously done in order not to
store "fat" value on the parser stack (also since non-POD values cannot
be stored in the `yylval` union).
2022-06-29 07:40:03 +01:00
Ulya Trofimovich 1fef8d161a Get rid of local_increment_t as it was only used in one place. 2022-06-29 07:40:03 +01:00
Ulya Trofimovich cc60dcb4f1 Update CONTRIBUTING.md: explain --enable-parsers / RE2C_REBUILD_PARSERS. 2022-06-29 07:40:03 +01:00
Ulya Trofimovich 6e91c22dfe Add CMake option RE2C_REBUILD_PARSERS (it requires Bison).
Previosuly CMake checked for Bison, and if it was present, then it
regenerated parsers and updated bootstrap files. Now it checks
RE2C_REBUILD_PARSERS, and if it is enabled, then CMake fails if it
cannot find Bison, regenerates parsers and updates bootstrap files.
2022-06-29 07:40:03 +01:00
Ulya Trofimovich 9e0dbd3c7c Add configure option --enable-parsers (regenerate parsers with Bison).
This fixes `make distcheck`, which previously failed when trying to
update bootstrap parser (it makes the source directory read-only. Now it
no longer fails because rebuilding parsers is disabled by default.

Also, cleanup Makefile.am implementation for rebuilding lexers with
RE2C_FOR_BUILD: there is no need to check that the re2c executable
exists, as it is done by configure.ac.
2022-06-23 07:53:18 +01:00
Ulya Trofimovich 4cb1a5d567 Consolidate and rename a few headers in src/util. 2022-06-22 23:40:50 +01:00
Ulya Trofimovich 8bb8100853 Rewrite SemAct to use slab allocator instead of a free list.
As this was the last remaining use of `free_list`, remove it altogether.
2022-06-22 08:12:39 +01:00
Ulya Trofimovich 731fb70b28 Use namespaces instead of classes with static functions. 2022-06-21 22:57:56 +01:00
Ulya Trofimovich 3dbc2801b9 Flatten file layout for encoding subsystem, merge small headers. 2022-06-21 22:45:39 +01:00
Ulya Trofimovich 1b1326ecf0 Rewrite RangeSuffix to use slab allocator instead of a free list. 2022-06-21 22:12:36 +01:00
Ulya Trofimovich d534094f20 Rewrite uniq_vector_t to behave more like std::vector.
Make `uniq_vector_t` inherit from `std::vector` and hide a few methods
instead of aggregating `std::vector` and wrapping some of the methods.
2022-06-21 08:26:47 +01:00
Ulya Trofimovich 265da45938 Move uniq_vector_t to util/containers.h. 2022-06-21 07:32:53 +01:00
Ulya Trofimovich f462d48347 Move lookup_t to util/containers.h. 2022-06-21 07:23:53 +01:00
Ulya Trofimovich 9535bbcaa6 Make membuf_t more like a container and move it to util/containers.h. 2022-06-21 00:09:04 +01:00
Ulya Trofimovich fdacb97620 Move to C++11: use uniform initialization syntax to reduce boilerplate. 2022-06-21 00:09:04 +01:00
Ulya Trofimovich 377fe6bf75 Rewrite AST construction, use slab allocator instead of a free list. 2022-06-21 00:09:04 +01:00
Ulya Trofimovich 90856c5f0b Move to C++11: replace typedef with using. 2022-06-19 11:13:02 +01:00
Ulya Trofimovich 2cebd41ed4 Move to C++11: use standard static_assert instead of a local one. 2022-06-19 10:48:44 +01:00
Ulya Trofimovich fbae2a09cc Move to C++11: use static constexpr instead of static const where possible. 2022-06-19 09:31:44 +01:00
Ulya Trofimovich a6f7defb42 Remove unused enum definition. 2022-06-18 19:55:18 +01:00
Ulya Trofimovich 812f80fac9 Move to C++11: convert enum lexer_state_t to enum class LexMode. 2022-06-18 18:57:04 +01:00
Ulya Trofimovich f6888dfdbd Move to C++11: convert enum AST::type_t to enum class AST::Kind. 2022-06-18 18:52:34 +01:00
Ulya Trofimovich e0e1e38db4 Move to C++11: convert enum Action::type_t to enum class Action::Kind. 2022-06-18 18:34:08 +01:00
Ulya Trofimovich a8f22e1c29 Move to C++11: convert enum nfa_state_t::type_t to enum class nfa_state_t::Kind. 2022-06-18 18:25:56 +01:00
Ulya Trofimovich b066007ca3 Move to C++11: convert enum RE::type_t to enum class RE::Kind. 2022-06-18 18:14:59 +01:00
Ulya Trofimovich 9040ace1a9 Move to C++11: convert enums in codegen to enum classes. 2022-06-18 17:52:14 +01:00
Ulya Trofimovich b83d4a5427 Move to C++11: use constexpr for UTF-8 constants. 2022-06-18 17:36:24 +01:00
Ulya Trofimovich f84e41959a Move to C++11: convert enum Enc::policy_t to enum class Enc::Policy. 2022-06-18 17:27:08 +01:00
Ulya Trofimovich d4845e2ec2 Move to C++11: convert enum Enc::type_t to enum class Enc::Type. 2022-06-18 17:17:28 +01:00
Ulya Trofimovich 57c79c13ca Autoformat re2c source code (with some manual tweaks).
This is the `astyle` command used for autoformatting:

    $ # run in source directory
    $ astyle --style=google \
             --max-code-length=100 \
             --align-pointer=type \
             --align-reference=type \
             --keep-one-line-statements \
             --suffix=none \
             --recursive '*'
2022-06-18 15:55:46 +01:00
Ulya Trofimovich dc8f264aa7 Remove TDFA(0) algorithm.
Benchmarks show that TDFA(1) is generally faster than TDFA(0); see the
official re2c website: https://re2c.org/benchmarks/benchmarks.html, or
the paper https://arxiv.org/abs/2206.01398 for details.

The benchmarks for TDFA(0) now use re2c-3.0 to build.
2022-06-13 23:15:50 +01:00
Ulya Trofimovich ac5c06ccb5 Remove staDFA algorithm.
Although it is an interesting algorithm, re2c benchmarks show that it
performs worse than TDFA(1): on complex regular expressions staDFA are
often much larger and slower than TDFA(1). See the benchmarks on the
official re2c website: https://re2c.org/benchmarks/benchmarks.html, or
the paper https://arxiv.org/abs/2206.01398 for details.

StaDFA implementation adds complexity to the most complex part of re2c
code -- determinization, and it takes some effort to maintain.

The algorithm is not fully documented and formalized: the original paper
by Chowdhury is incomplete, and the implementation is re2c had to use a
few fixes and modifications to make it work.

The benchmarks for staDFA now use re2c-3.0 to build.
2022-06-13 21:44:17 +01:00
Ulya Trofimovich ad7451a7f1 Move to C++11: define move ctor/assgnment in addition to copy ones. 2022-06-12 07:34:26 +01:00
Ulya Trofimovich a939a6eb9e Move to C++11: use 'default' keyword for copy ctor/assignment. 2022-06-11 23:21:56 +01:00
Ulya Trofimovich 753c09148f Move to C++11: use 'delete' keyword to forbid copying. 2022-06-11 23:09:02 +01:00
Ulya Trofimovich 98aa445546 Move to C++11: use range-for where possible. 2022-06-11 22:59:31 +01:00
Ulya Trofimovich 0aff7b9eae Move to C++11: fix a couple of -Wshadow warnings and use range-for. 2022-06-10 22:46:26 +01:00
Ulya Trofimovich b8f465ab29 Disable -Wzero-as-null-pointer-constant on re2c-generated code.
The generated code contains NULL in registed operations on TDFA
transitions (NULL is the default value for negative tags).
2022-06-10 22:30:19 +01:00
Ulya Trofimovich 0a5b271919 Move to C++11: convert enum gor_status_t to enum class GorPass. 2022-06-10 22:02:14 +01:00
Ulya Trofimovich 9e99220894 Move to C++11: specify underlying type for enum DirConf. 2022-06-10 21:50:09 +01:00
Ulya Trofimovich 2c0f9534b7 Move to C++11: convert enum VarType to enum class. 2022-06-10 21:45:31 +01:00
Ulya Trofimovich c191626dc7 Move to C++11: convert enum CodeKind to enum class. 2022-06-10 21:40:53 +01:00
Ulya Trofimovich 1d8d605c1c Move to C++11: convert enum posix_prectable_alg_t to enum class PosixPrecedenceTable. 2022-06-10 21:25:32 +01:00
Ulya Trofimovich 07dd1ce127 Move to C++11: convert enum posix_closure_t to enum class PosixClosure. 2022-06-10 21:15:15 +01:00
Ulya Trofimovich adab705372 Move to C++11: convert enum dfa_minimization_t to enum class Minimization. 2022-06-10 21:03:11 +01:00
Ulya Trofimovich 32c8bc40c7 Move to C++11: convert enum empty_class_policy_t to enum class EmptyClassPolicy. 2022-06-10 20:57:08 +01:00
Ulya Trofimovich 43efb026d2 Move to C++11: convert enum InputBlockKind to enum class InputBlock. 2022-06-10 08:16:26 +01:00
Ulya Trofimovich 2bac195bf8 Move to C++11: convert enum parse_opts_t to enum class ParseOpts. 2022-06-10 08:11:27 +01:00
Ulya Trofimovich 29711e6274 Move to C++11: convert enum fixed_tags_t to enum class FixedTags. 2022-06-10 08:05:39 +01:00
Ulya Trofimovich 8fb9f969ea Move to C++11: convert enum api_style_t to enum class ApiStyle. 2022-06-10 08:02:13 +01:00
Ulya Trofimovich fe39a5f1e7 Move to C++11: convert enum input_api_t to enum class Api. 2022-06-10 07:58:19 +01:00
Ulya Trofimovich 48352fbf23 Move to C++11: convert enum lang_t to enum class Lang. 2022-06-10 07:50:43 +01:00
Ulya Trofimovich 502aa69d13 Move to C++11: convert enum target_t to enum class Target. 2022-06-10 07:50:31 +01:00
Ulya Trofimovich 12808cb1d1 Move to C++11: use std::unique_ptr instead of a custom smart pointer. 2022-06-10 07:25:59 +01:00
Ulya Trofimovich 04b049f8c2 Move to C++11: replace NULL with nullptr.
One exception is the files generated by re2c (it uses NULL for tags).
2022-06-09 23:43:58 +01:00
Ulya Trofimovich 9c007557e1 Fix comment: fopen 'x' specifier (exclusive) is C11, but C++17. 2022-06-09 23:04:40 +01:00
Ulya Trofimovich b1b246b4a3 Move to C++11: replace custom <stdint.h> with a standard one. 2022-06-09 22:55:32 +01:00
Ulya Trofimovich d2a833a899 Autoconf, CMake: switch to C++11. 2022-06-09 22:27:17 +01:00
Ulya Trofimovich ce8501e27b Autoconf, CMake: check for python version >= 3.7.
This fixes bug #405 reported by Daniel Macks
"Insufficient version-check for python (run_tests.py failures)".

For CMake, prefer manual check to avoid raising required CMake version
to 3.19, in which find_package() learned to do version check.
2022-06-09 21:57:15 +01:00
Ulya Trofimovich 56df6e6146 Benchmarks: json2pgfplot.py: use correct font to render captions. 2022-06-09 08:19:40 +01:00
Ulya Trofimovich fa94d9c777 TDFA paper (co-authored with Angelo Borsotti). 2022-06-08 07:54:45 +01:00
Ulya Trofimovich c6bf3fc356 Benchmarks (Java): add results. 2022-05-30 22:42:12 +01:00
Ulya Trofimovich 0899f16e63 Benchmarks (DFA-JIT): update results. 2022-05-30 22:42:12 +01:00
Ulya Trofimovich a5be4db2b3 Benchmarks (DFA-AOT): update results, add helper script. 2022-05-30 22:42:12 +01:00
Ulya Trofimovich f4b4abbe7a Benchmarks: specialize json2pgfplot.py for each type of benchmark.
Changes in json2pgfplot.py:

- add mandatory argument --variant <dfa_aot | dfa_jit | nfa>
- for DFA-AOT benchmark show time and size results on the same page
- for DFA-AOT/DFA-JIT add header, drop labels on all but the 1st column
- make bars colorful
- for rows that don't fit replace three dots with a thick arrow
- automatically make DFA-JIT and NFA benchmarks relative

Also, remove some unnecessary cases from DFA JIT benchmark (they are
very similar to other cases and add little extra value).
2022-05-30 22:42:12 +01:00
Ulya Trofimovich e9ed0c8d25 Makefile.am: drop check for re2c executable in a bison rule.
The check makes no sense (parser is regenerated if there is bison, and
it is not related to re2c bootstrapping itself). The bootstrapping
process was changed in commit 967540566b,
and the check was likely left by mistake.
2022-05-30 22:42:12 +01:00
Ulya Trofimovich 0687500e8a Benchmarks: use '/usr/bin/env' instead of '/bin/env' in a script. 2022-05-30 22:42:12 +01:00
Ulya Trofimovich ea3c3ba9bc Benchmarks: update scripts that get Ragel and Kleenex.
Ragel:
  - Patch `/bin/bash` to `/usr/bin/env bash` to build Colm on NixOS.
  - Configure Colm with `--disable-manual` to avoid Asciidoc dependency.

Kleenex:
  - Use `cabal build` instead of the removed `cabal v1-sandbox`.
2022-05-30 22:42:12 +01:00
Ulya Trofimovich 058e266ece Benchmarks: regenerated re2c benchmarks with the latest re2c version. 2022-05-30 22:42:12 +01:00
Ulya Trofimovich 5cd639f341 Add MAINTAINERS.md with a list of things that should be removed first. 2022-05-30 22:41:50 +01:00
Ulya Trofimovich 34cb2e1a5a Add IDEAS.md with (as the name suggests) some ideas for the future. 2022-05-30 18:31:21 +01:00
Sergei Trofimovich 2a078d56e9 .github/workflows/benchmarks.yml: update apt indices for benchmarks as well
ci.yml already updates indices to pull in most recent packges.
Let's update benchmarks as well.
2022-03-30 13:01:28 +01:00
Sergei Trofimovich 2103838454 .github/workflows/ci.yml: always use latest apt state, not the outdated OS default 2022-03-30 10:07:43 +01:00
Sergei Trofimovich 55673eda5c .github/workflows/ci.yml: set up trivial apt cache
CI runs occasionally fail to fetch apt packages due to unavailable
remote. Let's try to cache heavyweight .deb packages and see if it
helps.

.deb files should not normally change frequently.
2022-03-30 10:07:43 +01:00
Ulya Trofimovich 814d38f7eb CMake presets: update Visual Studio version to 2022.
This fixes CI builds on windows (following the recent Github Actions
environment update).
2022-02-20 16:51:20 +00:00
Ulya Trofimovich d7d8e9d691 libre2c: multi-pass TDFA: compress identical backlinks into one.
Configurations with the same origin TNFA state also have identical
transition tags (by TDFA(1) construction those are the lookahead tags in
the origin configuration), therefore backlinks for such configurations
are identical and can be collapsed into one (provided that indices in
other backlink arrays that point into this one are suitably adjusted).
2022-02-20 16:51:20 +00:00
Ulya Trofimovich 38864aa327 libre2c: multi-pass TDFA: reduce lifetime of determinization context.
Determinization context was needed at `regexec` time previously, when
tag sequences on TDFA transitions were fetched from the tag tree. Now
that they are stored as arrays, tag tree is no longer needed and there
is no reason to keep determinization context alive after TDFA is
constructed.
2022-02-20 16:51:20 +00:00
Ulya Trofimovich 183d49137e libre2c: multi-pass TDFA: remove unused field in backlink structure. 2022-02-20 16:51:20 +00:00
Sergei Trofimovich 31c914f982 run_tests.py.in: add --verbose flag, disable successful printing by default
re2c test are so fast that text output in terminal takes comparable time
on slower terminals. Let's disable it by default. Can still be brought
back with --verbose option.
2022-02-20 12:14:03 +00:00
Ulya Trofimovich 9a143f45be C backend: do not emit comma after the last condition in enumeration.
Otherwise there is a warning when compiling in C90 mode:

    warning: commas at the end of enumerator lists are a C99-specific
             feature [-Wc99-extensions]

This fixes bug #395 "commas at the end of enumerator lists".
2022-02-04 07:28:29 +00:00
Ulya Trofimovich 3a7c3fedf2 Release 3.0. 2022-01-27 08:41:08 +00:00
Ulya Trofimovich e6cd3eaaec Update CHANGELOG. 2022-01-24 23:11:59 +00:00
Ulya Trofimovich f18ce1b7d3 Update README.md and BUILD.md. 2022-01-24 07:38:02 +00:00
Ulya Trofimovich f8ea4ea47d Fix the build on FreeBSD.
The build was broken by https://github.com/skvadrik/re2c/pull/376, which
added define of _POSIX_SOURCE to unbreak the build on Cygwin. The build
on FreeBSD is fixed by additionally defining _POSIX_C_SOURCE, which is
required by fdopen.
2022-01-23 19:40:18 +00:00
Ulya Trofimovich e262466260 Adjust build script for non-multilib environments.
Instead of passing compiler and linker option -m32, call 32-bit compiler
binaries directly (prefixed with "i686-pc-linux-gnu-"). This allows one
to run the script on NixOS where it's hard to get a system-wide multilib
environment.
2022-01-23 10:48:49 +00:00
Ulya Trofimovich 85dab53916 Add missing header include. 2022-01-23 10:23:40 +00:00
Ulya Trofimovich 38a07a3304 Rust backend: add example of a C lexer contributed by Perry Metzger. 2022-01-22 20:51:56 +00:00
Ulya Trofimovich 039c189491 Emit an error when repetition lower bound exceeds upper bound.
Historically this was allowed and re2c swapped the bounds. However, it
most likely indicates an error in user code and there is only a single
occurrence in the tests (and the test in an artificial one), so although
the change is backwards incompatible there is low chance of breaking
real-world code.

This fixes second test case in the bug #394 "Stack overflow due to
recursion in src/dfa/dead_rules.cc" (the actual fix is to limit DFA size
but the test also has counted repetition with swapped bounds).
2022-01-21 23:30:04 +00:00
Ulya Trofimovich a3473fd7be Limit maximum allowed NFA and DFA size.
Instead of failing with an out of memory exception or crashing with a
stack overflow, emit an error message and exit. This is a partial fix
for bug #394 "Stack overflow due to recursion in src/dfa/dead_rules.cc",
where re2c hit stack overflow on a counted repetition regexp with high
upper bound.

The patch adds the following limits:
  1. the number of NFA states
  2. NFA depth (maximum length of a non-looping path from start to end)
  3. the number of DFA states
  3. total DFA size (sum total of all NFA substates in all DFA states)

There are tests for the first three limits, but not for the DFA size as
all examples that trigger this behavior take a long time to finish (a
few seconds), which increases test run time almost twice.
2022-01-21 21:58:20 +00:00
Ulya Trofimovich aa02264d2f More documentation updates (rewrote parts of different sections). 2022-01-20 08:23:09 +00:00
Ulya Trofimovich d9f431c9bd Small fixes in a few more examples.
- Add `assert` to the basic C example (to clarify the intent).
- Change `types:re2c` to its new alias `conditions:re2c`.
2022-01-19 07:38:06 +00:00
Ulya Trofimovich f3016baacb Restructure a few initial sections in the manual. 2022-01-15 20:10:02 +00:00
Ulya Trofimovich 638c1db7fc Update docs following recent example changes. 2022-01-15 19:06:24 +00:00
Ulya Trofimovich 37cfc0b63f Rust backend: add a test for function-like API.
Function-like API is difficult to use in Rust, because API primitives
cannot be defined as functions or hygienic macros (they do not accept
all the necessary parameters), and closures are problematic due to the
borrow checker (in this test `Cell` is used as a workaround).
2022-01-15 09:28:35 +00:00
Ulya Trofimovich c01efa343a Unify the basic example across language backends. 2022-01-15 09:26:22 +00:00
Ulya Trofimovich 4dc0a787ee Examples: avoid explicit YYFILL call when initializing lexer state.
Instead, add more comments explaining how the lexer state is initialized
and why YYFILL is triggered automatically.
2022-01-15 09:08:05 +00:00
Ulya Trofimovich 9054e09967 Docs: update configuration description. 2022-01-14 22:21:22 +00:00
Ulya Trofimovich ff18b2b5b4 Docs: describe new options and new aliases for old options. 2022-01-13 07:28:14 +00:00
Ulya Trofimovich 769ecc83c7 Docs: add initial documentation for Rust. 2022-01-12 08:52:37 +00:00
Ulya Trofimovich 87f0fb454b Docs: regenerate manpages for C and Go with updated examples. 2022-01-10 23:51:43 +00:00
Ulya Trofimovich 644a151070 Cosmetic fixes in examples for all backends. 2022-01-10 22:39:43 +00:00
Ulya Trofimovich e0c7d453e3 Rewrite POSIX captures example for C and Go backends. 2022-01-10 07:34:26 +00:00
Ulya Trofimovich 38226f2a6b Rust backend: add example of submatch extraction with POSIX captures. 2022-01-09 20:46:23 +00:00
Ulya Trofimovich 1d515be714 Rewrite m-tags example for C and Go backends. 2022-01-09 17:07:44 +00:00
Ulya Trofimovich b48833c5a7 Rust backend: add example of submatch extraction with m-tags. 2022-01-09 16:21:54 +00:00
Ulya Trofimovich ee88b9670a Rewrite s-tags example with YYFILL for C and Go backends. 2022-01-08 19:58:50 +00:00
Ulya Trofimovich f8aa528686 Rust backend: add example of submatch extraction with s-tags and YYFILL. 2022-01-08 19:58:50 +00:00
Ulya Trofimovich 552ba7e687 Rewrite s-tags example for C and Go backends.
The new example parses semantic versions, while the old one parsed
IPv4 addresses. The new example demonstrates a conditional tag, as the
last version part may be missing.
2022-01-07 23:03:28 +00:00
Ulya Trofimovich 2251d3813a Rust backend: add example of submatch extraction with s-tags. 2022-01-07 08:20:35 +00:00
Ulya Trofimovich 6df5cc4024 Rust backend: add another example of reuse mode (!use directive). 2022-01-06 08:36:52 +00:00
Ulya Trofimovich faffbd78a7 Rust backend: add example of reuse mode (use:re2c blocks). 2022-01-06 08:09:03 +00:00
Ulya Trofimovich f60aedbf65 Rust backend: add example with include directives. 2022-01-05 23:49:41 +00:00
Ulya Trofimovich 282fbc0791 Simplify example for autogenerated header feature (for C, Go, Rust). 2022-01-05 23:49:41 +00:00
Ulya Trofimovich bb27b0e6ef Rust backend: completely disable line directives.
This is necessary because some parts of codegen conditionally generate
newlines depending on the line directives option. In Rust mode, unless
line directives are disabled codegen generates redundant newlines (e.g.
for the `stags:re2c` directive).
2022-01-05 23:03:52 +00:00
Ulya Trofimovich 2d60c74d00 Rust backend: add example with an autogenerated header. 2022-01-05 08:42:35 +00:00
Ulya Trofimovich c05af363e6 Go backend: use loop label to avoid potential continue ambiguity. 2022-01-05 07:31:15 +00:00
Ulya Trofimovich ef05cd2bc0 Add configuration re2c:label:yyloop.
The default is empty for C or Go, and "'yyl" for Rust.
2022-01-04 23:30:46 +00:00
Ulya Trofimovich 58c71a9e3f Rust backend: use loop label to avoid potential continue ambiguity. 2022-01-04 23:17:06 +00:00
Ulya Trofimovich 3ec2e646fa Rust backend: add example with blocks (functions) instead of conditions. 2022-01-03 14:42:16 +00:00
Ulya Trofimovich cca31d2225 Do not generate redundant YYPEEK statements.
YYPEEK statement is redundant if the assigned `yych` value is
overwritten before it is read. This may happen if a state has a single
transition to a non-move state (so there is no need to match on `yych`).
Transitions to a move state is different because a move state does not
have its own YYPEEK (it relies on a previously read `yych` value).
2022-01-02 23:35:04 +00:00
Ulya Trofimovich 919570c46a Do not allocate indices for unused state labels (in goto/label mode).
This change affects nearly every test (with the exception of tests for
errors that abort before code generation, and tests that use loop/switch
approach that have been updated earlier).

Since the change affects so many tests, it is impossible to verify
manually, but skeleton tests pass (and they actually compile and run the
generated code).
2022-01-02 17:06:24 +00:00
Ulya Trofimovich 82b704f693 Do not allocate indices for unused state labels (in loop/switch mode). 2022-01-02 16:47:44 +00:00
Ulya Trofimovich a46f01e603 Do not generate YYDEBUG statements for unused states labels.
Currently DFA states with unused labels still have their own index, but
this will change soon and there won't be any state number to pass to
YYDEBUG. This patch prepares the code by removing YYDEBUG statements for
states with unused labels.

One exception is the initial label: it may be unused (if there are no
transitions into the initial state), but still have a valid index. Keep
YYDEBUG statements for the initial label as they may be useful.
2022-01-02 16:38:41 +00:00
Ulya Trofimovich 705e687028 Split label generation and numbering into separate passes.
Labels should be generated before DFA transitions, because the pass that
generates transitions performs used label analysis: for every transition
its destination state label is marked as used. However label indices
should be assigned after used label analysis, otherwise indices may be
assigned to unused labels.

This is particularly important with the loop/switch approach, as label
indices map to `yystate` switch cases which should have consecutive
numbers.

This patch does not change label numbering yet, it only prepares the
code for the change (so no tests are updated).
2022-01-02 15:42:44 +00:00
Ulya Trofimovich 99ff66bc23 Add run scripts for a few test directories.
The scrips heuristically check if a test is complete (can be compiled
and run as a standalone program) and if so, compiles and runs it.
2022-01-02 15:37:04 +00:00
Ulya Trofimovich 2e7935e569 Optimize loop/switch code: avoid redundant looping via yystate switch.
As long as the following state has no incoming transitions (its label is
unused), generate it as a continuation of the current state. This avoids
looping through the `yystate` switch only to return to the next case.

The optimization is based on used label analysis for DFA state labels.
2021-12-31 23:22:17 +00:00
Ulya Trofimovich 51d3808418 Move used label analysis before the actual codegen.
This is necessary in order to generate better code with loop/switch
(avoid looping through the `yystate` switch in cases when the only
transition from a DFA state goes to the state immediately following the
current one). For that we need to know which DFA states are used (have
incoming transitions) before actually generating them.

Previously used label analysis was needed only to avoid generating
unused labels with goto/label approach. Since the decision whether to
output a label or not is taken at a late stage in codegen, it was ok to
perform the analysis when generating the states. With the loop/switch
approach this is no longer sufficient.

This patch moves used label analysis to an earlier codegen pass. A few
special labels are still handled at a late phase (such as the start
labels of blocks, some of which are only marked as used after expanding
`getstate` directives). These few exceptions do not affect DFA state
labels that matter for the loop/switch approach.
2021-12-31 23:22:17 +00:00
Ulya Trofimovich 1d72fbe950 Rust backend: add a Unicode example. 2021-12-28 12:48:10 +00:00
Ulya Trofimovich 0fcedefbfb Rust backend: emit correct code with -s, --nested-ifs option.
In Rust there is no implicit coersion between `u8` and `char` literals,
so it is necessary to emit hexadecimal literals in `yych` comparisons.
2021-12-28 12:21:24 +00:00
Ulya Trofimovich 005cdc7b84 Rust backend: add YYFILL example. Refactor examples for other backends.
Try to make YYFILL examples coherent across different backends.
2021-12-27 22:24:13 +00:00
Ulya Trofimovich d191cd86ac Rust backend: use isize as condition type in storable state mode.
With storable states `yystate` may have value -1, so it needs to have
signed type. Conditions have the same type as they are assigned to
`yystate`.

Also add a test for the combination of storable state and conditions.
2021-12-27 14:50:42 +00:00
Ulya Trofimovich d40ed35011 Rust backend: always generate braces around if body. 2021-12-27 13:37:58 +00:00
Ulya Trofimovich 8727e11e85 Emit better code for -1 state in loop/switch mode.
In loop/switch mode case -1 should be the same as case 0. Previously
the generated code handled these two as different cases, but they should
be handled as one case with a range of values.

This commit allows using ranges not only for characters (the switch on
`yych`), but also for numbers (the switch on `yystate`). In storable
state mode -1 is appended to the range of the first case 0.
2021-12-27 13:37:58 +00:00
Ulya Trofimovich 32a757f84c Rust backend: add an example for storable state. 2021-12-27 13:37:58 +00:00
Ulya Trofimovich 1bd47e0244 Rust backend: in storable state mode handle -1 state correctly.
With loop/switch approach (which is implied for the Rust backend) case
-1 is the same as case 0. Normally this is handled by falling through
from case -1 to case 0, but since Rust doesn't have fallthrough it is
necessary to set `yystate` to 0 and loop back to the head of the switch.
2021-12-27 12:06:30 +00:00
Ulya Trofimovich 87f335c560 Correctly parse single-line comments in indented semantic actions.
Semantic actions that start with `:=` are not enclosed in curly braces,
so re2c uses indentation to find the end of user-defined code: as long
as a line has nonzero indentation it is parsed as a continuation of
semantic action. In order to do that re2c needs to analyze if a newline
is followed by a whitespace. Previously this analysis was missing in the
case of newlines in single-line comments.
2021-12-24 21:38:00 +00:00
Ulya Trofimovich dba7d055aa Restrict lexical contexts where %{ is recognized as a block start.
As Krishna noticed in bug #392 "Cannot compile when user c string has a
special pattern", `%{` in the middle of a string makes re2c think that
this is a start of a re2c block. The user has to braek the string in two
in order to separate `%` from `{`.

The problem is exacerbated by the fact that `%{` does not require -F,
--flex-support option. It affects all re2c programs.

In general re2c cannot be sure if `%{` appears in the middle of a
string, a comment, a macro defintion or some other lexical context where
it is a part of a larger lexeme and not a standalone block start marker.
This is because re2c doesn't parse user-defined code in-between re2c
blocks (doing that would require implementing multiple language
frontends in re2c, which is out of the question).

This commit mitigates the problem in #392 by restricting lexical context
wheer `%{` is recognized as a block start: the marker must be on a new
line, optionally preceded by whitespace characters. This does not cover
all the cases and it may break some re2c programs that used block start
`%{` in other lexical contexts, but it is a reasonable compromise
between usability and backards compatibility.
2021-12-24 14:20:32 +00:00
Ulya Trofimovich 92c1a456ae Github Actions: fix path for uploading artifacts when the build fails.
Reorder steps so that 'Get build dir' step is executd before build and
test steps. Otherwise if the build or test steps fail, subsequent steps
are skipped and the path for uploading artifacts is not set properly.
2021-12-19 11:46:27 +00:00
Ulya Trofimovich f80c4995de Update configuration names in examples. Cosmetic formatting changes. 2021-12-19 11:46:27 +00:00
Ulya Trofimovich 0716f1d59b Use option alias --header instead of --type-header in tests and examples. 2021-12-19 11:46:27 +00:00
Ulya Trofimovich 886b73af33 Provide simpler names for some re2c options.
For example, --type-header should be just --header: it used to be for
`/*!types:re2c*/` directives initially, but after the addition of
`/*!header:re2c...*/` it may contain anything.

Also, --input is confusing and should be --api, as we refer to this as
"generic API" or "default API" in the documentation.
2021-12-19 11:46:27 +00:00
Ulya Trofimovich 091df3ab02 Update message for -Wcondition-order warning. 2021-12-17 23:02:04 +00:00
Ulya Trofimovich ad2ddd249c Add directive conditions:re2c (an alias for types:re2c).
Also guard against confusing error when instead of a local block
`local:re2c` the user specifies a named block `re2c:local`.
2021-12-17 22:41:35 +00:00
Ulya Trofimovich 45dbbe88b1 Revise re2c configurations, provide simpler aliases for some.
Configurations have evolved over time, and some of the names are quite
illogical. For example `re2c:flags:tags` should be just `re2c:tags`,
and `re2c:flags:unicode` should be `re2c:encoding:utf-32`. While we
cannot remove the old names (that would break existing programs), we can
still provide simpler and more logical aliases.

Take that opportunity to clean up configuration lexer a bit.
2021-12-17 22:02:42 +00:00
Ulya Trofimovich 4c88da02c5 Add option --no-unsafe and configuration re2c:flags:unsafe.
This allows to suppress generation of `unsafe { ... }` wrapper around
YYPEEK (for the Rust backend). Normally YYPEEK should avoid bounds
checks, as the lexer already does them (and goes to great lengths in
order to minimize the number of checks). However it may be useful to
enable bounds checks in YYPEEK for debug purposes, or just extra safety.
In that case the new option/configuration is needed to avoid warnings
emitted by the Rust compiler about redundant `unsafe`.

Also extend the script that compiles and runs examples for Rust to run
each test twice: first with the unsafe YYPEEK definition, and second
time after patching it to avoid `unsafe`. This allows to check that the
examples do not have trivial memory errors.
2021-12-15 22:53:26 +00:00
Ulya Trofimovich f081edd09e C backend: fix a memory leak in one of the examples.
Build and run examples with LeakSanitizer and AddressSanitizer.
2021-12-15 22:45:27 +00:00
Ulya Trofimovich 01a46937a0 Rust backend: avoid redundant braces around sematic actions.
Normally sematic are surrounded by line directives, so they occupy
multiple lines and should be wrapped in curly braces. In Rust there are
no line directives, but the codegen was still confused by empty stubs
and rendered semantic actions as multiline code blocks.

In order to fix this, it was necessary to separate removal of empty
code blocks into a separate pass (previously it was a part of `combine`,
but `combine` is too specialized and does not remove all empty blocks).
2021-12-14 00:17:56 +00:00
Ulya Trofimovich 0575cf7291 Rust backend: suppress warnings about unused yych initializer.
It is necessary to initialize `yych` (even though the initial value will
never be used) because in Rust a potentially uninitialized variable is a
compilation error. However, in cases when the compiler is able to see
that the variable is overwritten on all code paths, it instead emits a
warning about unused assignments.

Suppress the warning with `#[allow(unused_assignments)]`.
2021-12-13 23:26:16 +00:00
Ulya Trofimovich 0ff77971aa Rust backend: add an example for conditions. 2021-12-13 22:28:09 +00:00
Ulya Trofimovich c9eb8622c3 Rust backend: fix codegen for condition enum.
Generate standalone constants for each condition instead of an enum in
order to avoid casting to `yystate` type on each operation.
2021-12-12 19:22:39 +00:00
Ulya Trofimovich ed88e12e60 C backend: change formatting of switch statements.
Do indent cases with the default indent string. Do not auto-align cases
that fit on one line with tabs, use a single space before the case body.
Tab alignment didn't work very well and required special handling (for
example with --case-ranges it had to be turned off, because case length
varies more than one tab).

Over a thousand of tests were updated, but all the changes are trivial.
2021-12-11 20:53:52 +00:00
Ulya Trofimovich 4131ae7244 Rust backend: add YYFILL example with re2c:eof. 2021-12-11 10:21:28 +00:00
Ulya Trofimovich 48f2a0ca10 Rust backend: add end-of-input example with generic API and re2c:eof. 2021-12-09 22:20:55 +00:00
Ulya Trofimovich 0c2dfbdd96 Rewrite Go examples to be normal programs with main rather than tests.
Also delete a useless configuration YYLESSTHAN in one example.
2021-12-08 23:46:02 +00:00
Ulya Trofimovich 6715a02339 Cosmetic fixes in the C examples (also delete a useless configuration). 2021-12-08 00:26:15 +00:00
Ulya Trofimovich 7a1d0aaf2d Rust backend: add end-of-input example with generic API and sentinel. 2021-12-07 22:39:38 +00:00
Ulya Trofimovich de5e439187 Rust backend: add a re2c:eof example. 2021-12-07 22:22:31 +00:00
Ulya Trofimovich 62c3c6a567 Rust backend: wrap YYPEEK in unsafe rather than the whole lexer.
Also restructure YYPEEK generation to avoid code duplication.
2021-12-06 23:40:22 +00:00
Ulya Trofimovich 9df4c535e9 Fix unused variable warning in non-debug mode. 2021-12-06 22:05:19 +00:00
Ulya Trofimovich 7a4b317288 Rust backend: fix YYMAXFILL generation, add a bounds-checking example. 2021-12-06 21:50:27 +00:00
Ulya Trofimovich 297ee84733 Clean up if-then-else code generation and fix it for Rust. 2021-12-06 07:31:58 +00:00
Ulya Trofimovich 92276e73a2 Rust backend: add example for sentinel-based end-of-input check. 2021-12-04 21:07:51 +00:00
Ulya Trofimovich 1501b4df45 Correctly lex Rust code with standalone single quotes.
When lexing code blocks we need to lex string literals because they may
contain closing brace symbol that would otherwise be erroneously lexed
as a real closing brace.

However, single quote in Rust may be either the beginning of a char
literal as in '\u{1F600}', or a standalone one as in 'label. In the
latter case trying to lex a generic string literal will consume a
fragment of the file until the next single quote (if any) and result in
either a spurios parse error, or incorrect generated code. Therefore in
Rust we try to lex a char literal, or else consume the quote.
2021-12-04 20:57:54 +00:00
Ulya Trofimovich 9198728b43 Rust backend: wrap lexer in "unsafe" to avoid it in user-defined code. 2021-12-04 16:53:11 +00:00
Ulya Trofimovich d5bbfbd41d Adjust Github Actions config and CMake presets for re2rust. 2021-12-04 09:15:36 +00:00
Ulya Trofimovich 0c0d674e1d Rust backend: add the first (working) example. 2021-12-04 09:09:22 +00:00
Ulya Trofimovich 27b0008c56 Adjust testing script for Rust. 2021-12-04 09:08:49 +00:00
Ulya Trofimovich 01046e779c Autotools: build re2rust (option RE2C_BUILD_RE2RUST is on by default).
Documentation is yet to be done, so do not add build rules for it.
2021-12-04 09:08:25 +00:00
Ulya Trofimovich 3c02670f0f CMake: build re2rust tool (option RE2C_BUILD_RE2RUST is on by default).
Documentation is yet to be done, so do not add build rules for it.
2021-12-04 09:08:25 +00:00
Ulya Trofimovich 59e3223d0d Rust backend: add support for basic cases. 2021-12-03 23:59:55 +00:00
Ulya Trofimovich 09161b1444 Go backend: render continuous character ranges in compact form.
Use a comma-separated list instead of multiple switch cases.
2021-12-03 23:38:12 +00:00
Ulya Trofimovich e7ffdc5574 Small cleanup in codegen function that renders switch cases.
The only updated test has insignificant changes (comment moved before
the colon in `case ... :`).
2021-12-03 23:17:58 +00:00
Ulya Trofimovich 4937938362 Use abstract variable types in codegen. 2021-12-02 23:21:11 +00:00
Ulya Trofimovich 7e21423866 Abort in the default case in loop/switch mode.
Except for C/C++ when `re2c:state:abort` is not set, as `abort()`
requires including a header, which we don't want to enforce on the user.
2021-12-02 22:36:09 +00:00
Ulya Trofimovich 38f2d1fcd4 Add option stub --lang rust (currently generates incorrect code). 2021-12-01 22:29:53 +00:00
Ulya Trofimovich 987e7e17c3 Add a test for loop/switch used with storable state and conditions. 2021-12-01 22:09:19 +00:00
Ulya Trofimovich 2c0dd72332 Always generate YYSETSTATE in final states in storable state mode.
If the user has an outer loop that goes via YYGETSTATE switch, they
would expect the next iteration of the loop to start from the intiial
state rather than from some YYFILL state left after the last YYFILL
invocation. This especially matters when there is no explicit
`getstate:re2c` and no user-defined code between the YYGETSTATE switch
and the lexer entry (which is always the case in loop/switch mode).

A lot of (54) tests have been updated (they now have additional
YYSETSTATE invocations). One of them (conditions/condition_08_cbif.c)
previously resulted in a crashing program on input file "??(??)", and
now due to the addition of YYSETSTATE it doesn't crash.

Also, use state -1 rather than 0 as the default one in loop/switch mode.
Although it is safe to use 0 (cases always start from zero), using -1 is
unifies it with goto/label mode, where 0 cannot be used (start label
does not have to be `yy0`). And -1 is always safe for both modes, as
the YYGETSTATE switch always has either a default case or an explicit -1
case that goes to the initial state.
2021-11-30 23:53:38 +00:00
Ulya Trofimovich d308e4ed6f Store Msg reference in Opt to give options access to warnings.
Options are managed by `Opt`, and warnings are managed by `Msg`. Both
are created in `main` and have the lifetime of the whole program, so it
is not difficult to connect them.
2021-11-28 21:04:41 +00:00
Ulya Trofimovich 61af1763fd Add missing <assert.h> include. 2021-11-28 18:12:02 +00:00
Ulya Trofimovich edf3cbbd3e CMake: create output directory before building docs.
Previously trying to run rst2man.py with an output file in a nonexistent
directory resulted in the following build error:

  $ cmake --preset=linux-gcc-debug-ootree-skeleton-full
  $ cmake --build --preset=linux-gcc-debug-ootree-skeleton-full
  ...
  [  1%] Generating src/msg/help.cc
  Unable to open destination file for writing:
    OutputError: [Errno 2] No such file or directory:
      '[...]/linux-gcc-debug-ootree-skeleton-full/src/msg/help.cc.1'
2021-11-28 18:03:29 +00:00
Ulya Trofimovich 06c85fb955 CMakePresets.json: inherit "full" configuration before "fast".
Otherwise variable definitions from "fast" configuration take precedence
over the "full" configuration, resulting in disabling some important
configrations, such as Go language support.

For example, if "fast" is inherited before "full" we have the following
incorrect configrations that sets RE2C_BUILD_RE2GO:BOOL="FALSE":

  $ cmake -S .. --preset=linux-gcc-release-ootree-skeleton-full
  Preset CMake variables:

    CMAKE_BUILD_TYPE="Release"
    CMAKE_CXX_COMPILER="g++"
    CMAKE_C_COMPILER="gcc"
    CMAKE_INSTALL_PREFIX:PATH="[CUT]/re2c/install"
    RE2C_BUILD_LIBS:BOOL="TRUE"
    RE2C_BUILD_RE2GO:BOOL="FALSE"
    RE2C_FOR_BUILD="[CUT]/re2c/install/bin/re2c"
    RE2C_REBUILD_DOCS:BOOL="TRUE"
    RE2C_REBUILD_LEXERS:BOOL="TRUE"

But if "full" is inherited after "fast" we have the following (correct):

  $ cmake -S .. --preset=linux-gcc-release-ootree-skeleton-full
  Preset CMake variables:

    CMAKE_BUILD_TYPE="Release"
    CMAKE_CXX_COMPILER="g++"
    CMAKE_C_COMPILER="gcc"
    CMAKE_INSTALL_PREFIX:PATH="[CUT]/re2c/install-2"
    RE2C_BUILD_LIBS:BOOL="TRUE"
    RE2C_BUILD_RE2GO:BOOL="TRUE"
    RE2C_FOR_BUILD="[CUT]/re2c/install/bin/re2c"
    RE2C_REBUILD_DOCS:BOOL="TRUE"
    RE2C_REBUILD_LEXERS:BOOL="TRUE"
2021-11-28 16:49:44 +00:00
Ulya Trofimovich 2d28bfea79 Make --loop-switch work with conditions.
Merge all conditions in one loop/switch where DFA for each condition has
its own set of cases. Use `yystate` variable to switch between
conditions in the same way as between DFA states.

The => rules set user-defined condition variable with YYSETCONDITION.
The :=> rules set `yystate` and continue to the head of the loop/switch.
2021-11-28 16:49:44 +00:00
Ulya Trofimovich 9d58618750 Respect define:YYGETSTATE:naked configuration in loop/switch mode. 2021-11-28 16:49:44 +00:00
Ulya Trofimovich c38c965434 For skeleton and .dot targets merge header file into the output file.
Header file may contain blocks with regular expressions and rules. They
should be handled as well as the blocks in the output file.

This patch fixed a failing skeleton test.
2021-11-28 16:49:40 +00:00
Ulya Trofimovich 96cacc78c0 Use initial state indices as condition numbers with --loop-switch.
Normally with the goto/label approach condition enumeration uses
implicit consecutive indices starting from zero. With the loop/switch
approach it is more convenient to represent conditions with their
initial DFA state index. This allows one to assign condition numbers to
the state variable `yystate` and get rid of the entry condition switch.
2021-11-28 16:48:30 +00:00
Ulya Trofimovich 6f2801248c Factor out block list construction into a separate function. 2021-11-28 16:48:30 +00:00
Ulya Trofimovich cbc33f36f5 Delay YYMAXFILL / YYMAXNMATCH computation until handling the directive.
The `maxfill:re2c` and `maxnmatch:re2c` directives may specify an
optional list of block names. If the list is specified, the directives
compute maximum value over the specified blocks, otherwise they compute
global maximum across all blocks in the program.

Previously the global maximum was prepared in advance even if the
directives were not used. This patch delays the computation of global
YYMAXFILL / YYMAXNMATCH until they are needed, as is already done in
the case when the directive specifies a list of blocks.
2021-11-28 16:48:30 +00:00
Ulya Trofimovich 41f503de5d Delay global tag list construction until handling the directive.
The `stags:re2c` and `mtags:re2c` directives may specify an optional
list of block names. If the list is specified, the directives gather
condition nems from the specified blocks, otherwise they use a global
set of tag names gathered across all blocks.

Previously the global set was prepared in advance even if the directives
were not used, but a set for specific block list was constructed only if
needed. This patch delays global set construction until it is needed and
unifies it with the case of a specific block list.
2021-11-28 16:48:30 +00:00
Ulya Trofimovich 64405f6f62 Do not autogenerate condition enum if there is an explicit types:re2c.
The rationale is, if the user specified an explicit `types:re2c`
directive, they probably do not want the autogenerated enum as well. If
for some reason they need multiple enum definitions (either in the
output file or in the header file), they can use multiple `types:re2c`
directives.
2021-11-28 16:48:26 +00:00
Ulya Trofimovich 64961bf692 Search for named blocks both in the output file and in header.
This fixes a test for condition enum: previously re2c emitted an error
because one of the `types:re2c` directives listed block name for a block
defined in another file, and re2c failed to find it. Now it finds it.
2021-11-28 16:46:56 +00:00
Ulya Trofimovich 9fdd7fca0b Do not generate empty condition enum.
Some compilers or language standards allow it, but generally it's more
likely to indicate an error in user code.

Fix a few tests that generated empty condition enum by mistake.
2021-11-28 16:46:56 +00:00
Ulya Trofimovich eb30417eed Clean up old tests for condition enum and header.
Replace a bunch of simple and similar tests with a few more
comprehensive ones that cover recent re2c features like named blocks and
block lists in the `types:re2c` directive, in addition to older features
such as the --type-header option.

One of the new tests reveals an error in re2c: it fails to find
conditions in header. The error will be fixed in a follow-up commit.
2021-11-28 16:46:56 +00:00
Sergei Trofimovich a6220b8f4b avoid using reserved identifiers (underscores)
clang with -Weverything detects these as:

    ./src/util/free_list.h:9:16:
      warning: identifier '_Ty' is reserved
      because it starts with '_' followed by a capital letter [-Wreserved-identifier]
    template<class _Ty>
                   ^
2021-11-28 16:46:56 +00:00
Sergei Trofimovich bbb9dae8a3 fix struct/class declaration mismatch (-Wmismatched-tags)
Detected by clang's-Weverything:

    ./src/regexp/re.h:17:1: warning: struct 'Msg' was previously declared as a class;
      this is valid, but may result in linker errors under the Microsoft C++ ABI [-Wmismatched-tags]
    struct Msg;
    ^
2021-11-28 16:46:56 +00:00
Ulya Trofimovich 53259db5e7 Make --loop-switch work with storable state.
With the loop/switch approach there is no `goto` statement, so it is
impossible to jump from a `getstate:re2c` block to an YYFILL label,
bypassing all the user-defined code in the middle (as it normally
happens with the goto/label approach).

Therefore `getstate:re2c` is forbidden with --loop-switch, and the
initial switch on storable state is merged into the `yystate` switch:

  - case -1 falls through to case 0 (the initial state)

  - transitions to YYFILL states are moved to cases that occupy
    contiguous numbers after the last regular DFA state

In order to make it possible to wrap the generated lexer in a
user-defined loop, an `YYSETSTATE(1)` statement is emitted in each final
state before the user-defined semantic action: if the action jumps to
the head of the outer loop, the next iteration will start from state -1,
as the user might expect. Note that `YYSETSTATE(1)` is not needed with
goto/label approach, because one can jump directly to the start label.
2021-11-28 16:46:56 +00:00
Ulya Trofimovich 28bc929bb6 Make --loop-switch and --eager-skip options non-configurable.
Having configuration for the --loop-switch option is only useful if one
needs to enable loop/switch approach on a per-block basis. Mixing the
two approaches (goto/label and loop/switch) would mean that some of the
blocks have start labels and can use cross-block transitions, while
others cannot. This would create confusion for whole-program directives
like `getstate:re2c` that cover multiple blocks.

With the loop/switch approach `getstate:re2c` should be forbidden, as it
requires a cross-block transition from the state switch to the lexer
entry, which is unsupported in the absence of the `goto` statement.
2021-11-28 16:46:52 +00:00
Ulya Trofimovich 031ddb7bb8 With --loop-switch, start state enumeration from zero in each block.
Normally with the goto/label approach re2c uses a program-wide state
enumeration that starts from zero and increases with each block. Since
each state has a label, global enumeration allows one to have multiple
blocks in the same function without the risk of label collision.
Moreover, different blocks can be connected with cross-block `goto`
transitions, so all state labels should have different numbers.

The situation is different with the loop/switch approach: there are no
labels and no cross-block `goto` transtions; instead every state has a
switch on the `yystate` variable. Since different block have different
switches, it makes sense to start state enumeration from zero in each
block (so that switch cases start from zero, and the zeroth case
corresponds to the start state of every block).
2021-11-28 16:41:17 +00:00
Ulya Trofimovich 8d219a6b27 Drop useless -c option in some of the Go examples.
These examples do not use conditions, so -c does nothing. It has been
accidentally copy-pasted from another example that uses conditions.
2021-11-28 16:41:17 +00:00
Ulya Trofimovich 1c244eb19b Add tests for the new --loop-switch option (for C and Go backends).
The added tests are copy-pasted from examples, but the generated code is
different: it uses loop/switch constructs instead of goto/label. All
tests except for conditions and storable state are valid programs that
can be compiled and run without errors.
2021-11-28 16:41:17 +00:00
Raekye c74080e656 Initial implementation of the --loop-switch option.
With this option, instead of the usual goto/label approach DFA is
wrapped in a loop with a `switch` statement on `yystate` variable. Each
DFA state is an individual `case`. Transitions between states are done
by setting the `yystate` variable to the numeric index of the target
state and executing `continue` that jumps to the head of the loop and
goes via the `switch` again. This is less efficient than direct jumps
with the goto/label approach, but it is the only way we can implement a
DFA for languages that do not have `goto` statement (such as Rust).

YYFILL labels are problematic for the loop/switch approach, because they
are normally in the middle of a DFA state (after the YYSKIP operation,
but before YYPEEK and transitions to other states). To fix this, we use
the --eager-skip option that moves YYSKIP operations from DFA states to
transitions.

The initial value of `yystate` is the numeric index (label) of the first
DFA state. It is _not_ the intiial label, because initial label does not
have a state (so there is no `case` in the `switch` for it), and it is
only needed to bypass YYSKIP operation in the first DFA state (which is
not there anyway because of the --eager-skip option).

Current limitations:
  - Conditions are not supported. We need a per-condition `yystate`, and
    ideally transitions between conditions should also use a loop/switch
    approach instead of goto/label (it will be required for Rust, but it
    is optional for C and Go).

  - Storable state is not supported. We need to rewrite user-defined
    code to use the same state variable as `yystate` and the one in
    `YYGETSTATE`/`YYSETSTATE`, as well as to put `getstate` block
    immediately before DFA entry (if there is any code between state
    dispatch and DFA entry, it needs to be bypassed when re-entering
    the lexer after YYFILL, which is easily done with goto/label
    approach in C and Go, but not in Rust that has no `goto`).

Test results with the --loop-switch option enabled by default:
  - Skeleton tests pass (320 soft errors).

  - Examples for C and Go compile and run without errors, except for
    conditions, storable state and cases when user-defined code needs to
    be rewritten (e.g. when it uses an outer loop and `continue`/`break`
    statements end up referring to the wrong loop).
2021-11-28 16:41:17 +00:00
Raekye cba165c27b Don't generate initial label if --eager-skip option is used.
The initial label is not needed in such cases as there is no need to
bypass YYSKIP statement (--eager-skip moves it from states to
transitions).
2021-11-28 16:41:17 +00:00
Raekye e73b93f61f Add stubs for --loop-switch option and related configurations.
The following has been added:
  - option --loop-switch
  - configuration `re2c:flags:loop-switch`
  - configuration `re2c:variable:yystate`

Currently they are no-ops.
2021-11-28 16:41:17 +00:00
Raekye 8011459a1e Move --eager-skip option from constant to mutable.
This is necessary to support the future --loop-switch option.

With --loop-switch we cannot have labels (goto targets) in the middle of
a state. This affects YYFILL labels which normally go after YYSKIP but
before YYPEEK. The --eager-skip option resolves the problem by moving
YYSKIP statements from states to transitions. The plan is to enforce it
automatically if --loop-switch is enabled, but since --loop-switch will
be a mutable option, --eager-skip also needs to be mutable.
2021-11-28 16:41:17 +00:00
Raekye 6695fcd3af Skeleton: use goto-loop instead of for-loop.
To support the future --loop-switch option, this change avoids
unexpected control flow with `continue`.

The skeleton tests are verified and updated.
2021-11-28 16:41:17 +00:00
Ulya Trofimovich 5ac98bc208 Correctly handle nested include files with identical paths.
The previous commit fixed bug #386 "#line directives around !include
contents" by reading every include directive twice: for the first time
on entry (when the file is included), and for the second time on exit
(when the file has been processed).

However that commit used a crude criterion to distinguish the first and
the second times: it compared the include file path (specified in the
include directive) to the path of the file on top of the stack. This
doesn't work for nested include files that have the same relative path.

This patch adds a test and fixes the problem by using a different
criterion: it checks if the parent file is topmost after popping all
finished files from stack (the comments in src/parse/scanner.cc explain
why this works in detail).
2021-11-28 11:29:41 +00:00
Ulya Trofimovich 48e83fcaab Mark start and end of included .re files with line directives.
This fixes bug #386 "#line directives around !include contents"
reported by Cyan Ogilvie.

It is easy to generate line directive at the beginning of the include
file, but much more difficult to find the end of it: file contents are
just a stream of bytes in the input buffer, and the continuation of the
parent file follows immediately after the end of the inlude file.

Therefore we use a hack and "unread" the include directive in the parent
file before filling the buffer with the contents of the include file (as
if the include directive appeared after the contens of include file).
This makes the lexer read the directive for the second time; at this
point we know it's the same include directive because the include file
is already on top of the file stack. So we ignore the directive and
simply generate line info.

The current implementation has a problem with nested includes that have
identical relative file paths. This will be fixed in a follow-up patch
by looking at the resolved paths when comparing files.
2021-11-27 12:16:48 +00:00
Ulya Trofimovich 7c6b5c955e Generate non-overlapping names for s-tag and m-tag variables.
This fixes bug #385 "mtag/stag automatic variable generation collision"
reported by Cyan Ogilvie.

Previously s-tag and m-tag variables used non-overlapping numbers
within a single DFA. With start conditions this is insufficient, as
variables in different conditions (DFAs) may have identical numbers.

If both tag variables are single-valued, or if they are both
multi-valued, having one variable is fine: there are no transitions to
or from the middle of DFA, so tag variables in different conditions are
never used at the same time.

However if one of the variables is single-valued and the other one
multi-valued (or vice versa), they cannot share the same tag variable.
To avoid collision in such cases, this patch gives m-tag variables an
extram "m" affix that makes them different from any s-tag variable.
S-tag variables do not get an "s" affix primarily to avoid updating over
600 tests. Tag variables are internal to re2c and the user should not
use them directly, so this change does not break user code.
2021-11-23 23:25:14 +00:00
Ulya Trofimovich 68e1ab7160 Correctly compute fixed tags in trailing context.
Tags in trailing context may be fixed on the rightmost cursor position.
Their values must be updated before cursor is reset to the position of
the trailing context, otherwise the values would be incorrect.
Previously this was not so, which resulted in incorrect tag values.

This fixes bug #380 "Tags incorrectly set with lookahead" reported by
Terry Sanders .
2021-11-04 23:51:01 +00:00
Ryan Mast 8920ef895b Setup Java for the benchmarks workflow using actions/setup-java 2021-11-02 07:25:00 +00:00
Perry E. Metzger 73dc6295a7 minor fixes to interface.rst_
Improve grammar, make some small style improvements, and keep the
lines consistently under 80 columns. Also update boostrap docs for
resulting changes.
2021-10-31 20:30:35 +00:00
Ulya Trofimovich 6d7c3cbb47 Small fixes in distcheck script.
Changes:
  - use 'sh' instead of 'bash' as interpreter
  - split build into stages 1 and 2 and rebuild lexers at stage 2
  - double-quote shell variables to make shellcheck happy
2021-10-24 13:10:47 +01:00
Ulya Trofimovich 072d49e59c Autotools: link google-benchmark binaries with pthread. 2021-10-22 16:52:36 +01:00
Ulya Trofimovich eb8720d5ea Use unsigned integers for register versions in TDFA states.
Previously we used negative numbers for register versions that were
allocated for transitions on negative tags. This is pointless, because
state mapping may biject positive versions to negative ones or vice
versa, erasing the distinction. And it wasn't used anyway.
2021-09-15 22:42:55 +01:00
Ulya Trofimovich b90b78c79c Mark each register as not interfering with itself.
Exclude diagonal pairs from interference table. This does not affect
subsequent register allocation, because the algorithm that partitions
registers into non-interfering classes does not check is a register
interferes with itself. So the fix does not affect the generated code,
except for one test that draws the interference table.
2021-09-04 09:41:08 +01:00
Ulya Trofimovich 6b434e934c run_tests.py: make tests fast again by fixing Wine check.
Commit ec1dc2b3ec incorrectly compared
Wine path against `None` to determine if the tests run under Wine. That
doesn't work as expected because the default value is empty string, not
`None`, so the checks always succeeded and as a result the script did
unnecessary work (patched newlines in the generated output). That made
it a few times slower.
2021-09-04 09:16:04 +01:00
Biswapriyo Nath 15376f4393 Define _POSIX_SOURCE for fdopen in cygwin
This fixes the error:
error: ‘fdopen’ was not declared in this scope; did you mean ‘fopen’?
2021-09-03 16:35:42 +01:00
Serghei Iakovlev dff1b6cd36 Provide support of CMake Presets
Since 3.19.8 CMake looks in the top source directory of a project for files
named CMakePresets.json and CMakeUserPresets.json. Neither file is required
to be present, but if the user tries to list or use presets, at least one of
the files must exist. If both files are present, they will effectively be
merged by reading the CMakePresets.json file first and then the
CMakeUserPresets.json file.

CMakePresets.json can be used to define presets for things like continuous
integration jobs or cross-compilation setups using toolchains provided as
part of the project. In general this feature allows us to simplify CI
configuration phase by taking out all the logic into presets-file and helps
us to make reproducible builds. From now on, you no longer need to carefully
read and copy all the flags locally in order to reproduce CI configuration or
build. Simple use the same one line command as at CI.

As a bonus, users of modern CMake can use a cross-platform and portable way
instead of build/__cmake*.sh scripts.

To see the list of available presets use:
    cmake --list-presets

To configure re2c use:
    cmake --preset=<NAME>

To build re2c use:
    cmake --build --preset=<NAME>

To test re2c use:
    cmake --build --preset=<NAME> --target tests

References:

- https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html
- https://gitlab.kitware.com/cmake/cmake/-/issues/21164
- https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#presets
2021-08-12 12:30:44 +01:00
Ulya Trofimovich aa2da70299 Release 2.2. 2021-08-01 10:05:50 +01:00
Ulya Trofimovich cf13205c63 Update CHANGELOG. 2021-08-01 08:34:40 +01:00
Ulya Trofimovich ec1dc2b3ec run_tests.py: patch newlines under Wine and get rid of Wine warnings. 2021-07-31 20:42:52 +01:00
Ulya Trofimovich a9ba2c4d91 Add forgotten includes to make headers self-contained. 2021-07-31 20:42:52 +01:00
Ulya Trofimovich 36e4a0e5ee run_tests.py: use a local reimplementation of shutil.copytree.
We need to copy multiple directories (test/ and examples/) into one
(temporary test directory). `shutil.copytree` is problematic for two
reasons:

 1) it requires `dirs_exist_ok` parameter which was added only in
    python-3.8

 2) `make distcheck` fails when trying to copy the second directory
    because it makes source files read-only
2021-07-31 09:10:28 +01:00
Ulya Trofimovich a779585cb3 split_man.sh: allow substitution RE2C_LANG_NAME -> {C,Go}. 2021-07-31 09:10:28 +01:00
Ulya Trofimovich 53ee23a54f Update docs: rewrite the introduction section of the manual. 2021-07-25 21:13:51 +01:00
Ulya Trofimovich 477f35b567 Travis CI: use Ubuntu 20.04 (Focal Fossa) to have Python 3 by default. 2021-07-25 11:08:03 +01:00
Ulya Trofimovich 1d84bb9816 Update Travis CI config. 2021-07-25 10:25:54 +01:00
Ulya Trofimovich f67f489281 Simplify interface code in Go tests with re2c:api:style = functions;. 2021-07-24 13:15:15 +01:00
Ulya Trofimovich 0bd2b72155 Add BUILD.md with build/test instructions. 2021-07-18 18:57:05 +01:00
Ulya Trofimovich 423c56ca55 Update documentation for directives. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 58f47cd066 Use new re2c features in re2c lexers to have some real-world coverage. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich fd2e96394f Slightly relax !use and !include directive format.
- allow optional spaces before the semicolon
- allow whitespace or the end of block after the semicolon (previously
  only a newline was allowed)
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 2a973270d9 Don't fail when meging symtabs with pointer-identical name definitions.
This may happen if a name is defined in global scope and inherited by a
`rules:re2c` block that is followed by another block that uses the rules
block with a `!use` directive:

  /*!re2c
      x = [x];
  */

  /*!rules:re2c:R
      // inherits 'x' definition from global scope
      y = [y];
  */

  /*!re2c
      // inherits 'x' definition from global scope
      // imports the same 'x' definition from 'R'
      !use:R;
  */

At the time when symtab from the rules block is merged with the
inherited one, there is a collision on the global names that are present
in both symtabs. It's harmless.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich a20d8965a9 Unify handling of getstate:re2c with other directives. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich a096166f83 Allow 'format' and 'separator' configuration in types:re2c.
Now it is possible to customize this directive:

  /*!types:re2c
      format = "static const int @@{cond} = @@{num}";
      separator = "\n";
  */
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 19be0e3ab7 Unify #line info for directives max, maxnmatch, stags, mtags.
Tests have been updated because `#line` directives are now generated in
more cases than previously.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 144dbc4146 Unify handling of directives max, maxnmatch, stags, mtags. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 7262325fbe Move the definition of codegen block kinds to constants.h. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 6bfd78133e Move constant definitions to a top-level header to reduce dependencies.
Also, add and remove a few files.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 92b98e9781 Deprecate configurations flags:i and flags:no-debug-info.
Global options `-i` and `--no-debug-info` can be used instead.

Configurations allow to enable/disable `#line` directives on a more
fine-grained basis (for selected parts of the file), but there's not
much point in doing so and there are no known real-world use cases.
Having them as global options is convenient, because a global option
can be used in parser (unlike a configuration, which can change and for
which the final value is unknown until the whole block is parsed).
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 7c278733fa Clean up a few places in codegen that have to use global options.
The few places are:
  - condition enum (this one should always use whole-program options)
  - state switch (this one should either use whole-program options, or
    block-local options if this is a `use:re2c` block

Add comments.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 02da15a2ef Store block pointer in codegen context instead on inlining its fields. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 2d1aec19ba Handle block lists in types:re2c directive. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 958ac86e51 Use block-specific condition prefix when generating condition enum. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich ca0ebe9c58 Handle block lists in stags:re2c and mtags:re2c directives. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 20236a1b04 Skeleton: emit global m-tag definitions only once (to avoid collisions). 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 43b6533936 Allow 'format' configuration in max:re2c and maxnmatch:re2c.
Now it is possible to customize these directives:

  /*!max:re2c
      format = "static const int YYMAXFILL = @@";
  */

  /*!maxnmatch:re2c
      format = "static const int YYMAXNMATCH = @@";
  */

This commit breaks backward compatibilty, because it forbids arbitrary
garbage at the end of `max:re2c` directive. It was historically allowed
and even used in one test, but it doesn't add any practical value and
it's getting in the way of adding 'format' option (or any other option).
The following code that was previously accepted now triggers an error:

  /*!max:re2c
      ... arbitrary g4rbage ...
  */
2021-07-17 21:38:36 +01:00
Ulya Trofimovich fa8e24f844 Pass struct to functions to reduce the number of parameters. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich e1fc740020 Split 1st pass codegen context into global and block-local parts. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich d91e137ca0 Handle block lists in maxnmatch:re2c directive. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 9383114bd6 Handle block lists in max:re2c directive. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 78c77ab417 Rename test subdirectory. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich d81c2ecd4e Point at the beginning of a block in warnings and error messages. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich ac4aaed276 Forbid duplicate names in block lists.
For example, emit an error on `/*!getstate:re2c:x:y:x */`. Previously
this resulted in code that would not compile (due to duplicate cases in
the generated state switch), but an explicit error message from re2c
is more user-friendly (and it covers all block lists, not just the case
of `getstate:re2c` directive).
2021-07-17 21:38:36 +01:00
Ulya Trofimovich ba7eec131c Forbid blocks to have identical names (including autogenerated ones). 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 480010a043 Append block number to autogenerated block name.
Previously autogenerated names were identified by block line, but it may
be non-unique (it is possible to have multiple blocks on the same line,
included files may define blocks at the same line, and line directives
may reset line number).
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 62ef4235cf Add tests for state switch (with -f --storable-state option). 2021-07-17 21:38:36 +01:00
Ulya Trofimovich f2fb9ac94c Improve error reporting when generating state switch.
Emit error messages instead of failing debug checks when:
- there are no blocks with code in the global state switch
- first named block on the list is empty (has no start label)
- a named block is missing (reworked error message)

Also, rewrite the code in a way that avoids looping over the block list
twice. Previosuly the first loop was used to to find a start label, and
the second loop was to generate switch cases. Now we do both in the same
loop and prepend the default case with the start label to other cases.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 89841a7a23 Split "expand" code generation pass into first and second passes.
The first pass expands everything except labels (they have to wait until
the second pass because the first pass may generate some additional uses
for previously unused labels). The second pass expands labels.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 93d39f384d Rework codegen for state switch with -f --storable-state option.
State switch is generated differenly for `use:re2c` blocks and for all
other blocks.

For use blocks there is a block-local switch that is automatically
generated at the beginning of the block. Previously use blocks had a
separate enumeration of YYFILL states starting from zero, and they used
a block-specific prefix in YYFILL state labels. Now use blocks
participate in the global YYFILL state enumeration, and their labels no
longer require a block-specific prefix (because label numbers are unique
across the whole file).

For all other blocks there is a global state switch that is generated
either at the point where `getstate:re2c` directive is specified by the
user, or (if there are no user-defined `getstate:re2c` directives) at
the beginning of the first non-use block that has a start label. Code
generation of the global state switch hasn't changed.

Now it has become possible to generate a state switch for the subset of
blocks specified in a `getstate:re2c` directive. The code is still
slightly incorrect, as the start label for the first block on the list
is not always generated (only if this block is the first non-use block
in the file). This happens because the generation of labels happens too
early, before the generation of the state switch that marks the start
label as used.

The tests that have use blocks have been updated (only the labels and
the autogenerated YYFILL state numbers have changed).

As a result of this patch the cases in a state switch no longer have to
start from zero and be sequential: 0, 1, 2,... . Now they can start with
any number and consist of block-local sequential ranges (the numbers are
unique and non-decreasing). State numbering is an internal re2c detail,
so it should not affect any users. State -1 (or any other negative
number) is handled in the same way as before (as a special case).

To facilitate the generation of state switch based on block names, the
code has been rewritten to find blocks by their name. Each block now
stores start and end YYFILL indices and a link to the start label. This
information is used in the generation of state switch instead of an
implicit assumption that indices start from zero and occupy sequential
numbers. Use blocks are also handled via the new name-based mechanism:
they use a special autogenerated block name which is passed to the
autogenerated block-local state switch.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 410c81e060 Give all input blocks a name (a user-defined or an autogenerated one). 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 703af40334 Rename input block enum and move it to a header with fewer dependencies. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich ac2c9ff132 Always count start label with -f --storable-state option.
Start label is not always used, only in cases when there is a transition
to the start state or if it is explicitly enforced by the user.

Previously re2c did not include start label in the global label
enumeration unless it was actually generated. This required knowing in
advance if the label was used or not. Currently we do have such
knowledge, because the default transition in the state switch goes to
the first block in the file (except for reuse blocks, which have
individual state switch).

But this is problematic for the new `getstate:re2c` that is allowed to
specify a list of block names, because the default transition now needs
to go to the first block on the list, not the first block in the file.

This commit adds start label to the global label enumeration, even if it
is not generated. As a result, label numbers in some tests have changed.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich f502e54357 Allow generating user-defined state switch multiple times. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 0ae6ed4675 Allow specifying block names in re2c blocks and directives.
Don't do anything with the specified names yet, just parse them and save
for future use. Follow-up changes will handle block names for each type
of block or directive.

The following block types now have an optional name:

    /*!re2c[:name] ... */
    /*!local:re2c[:name] ... */

The following directives now have an optional list of colon-separated
block names:

    /*!max:re2c[:name1[:name2...]] ... */
    /*!maxnmatch:re2c[:name1[:name2...]] ... */
    /*!types:re2c[:name1[:name2...]] ... */
    /*!getstate:re2c[:name1[:name2...]] ... */
    /*!stags:re2c[:name1[:name2...]] ... */
    /*!mtags:re2c[:name1[:name2...]] ... */
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 15cc78861a Add local blocks (declared with /*!local:re2c ... */).
The new type of blocks differs from the usual `/*!re2c ... */` blocks
in that the names and configurations it defines are local: they have the
scope of a block and aren't visible outside of it in the global scope.
This allows one to reuse the same names multiple times in different
blocks, and to avoid "polluting" the global scope.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich ac5a710548 Use correct symbol table for each block.
Symbol table (a.k.a. the mapping of named definitions to regexps) should
obey the same scoping rules as configurations. Before this commit it was
broken: there was one global symbol table that accumulated all named
definitions along the way.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 8d97e4b5be Make run_tests.py executable on UNIX (lost when migrating to python). 2021-07-17 21:38:36 +01:00
Ulya Trofimovich 2c4d5c8c06 run_tests.py: don't pass nonexistent parameter to function. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich b6c96f92ea run_tests.py: don't crash if some expected output files are missing. 2021-07-17 21:38:36 +01:00
Ulya Trofimovich ae4e534bc8 run_tests.py: don't crash when reference results are missing.
Run tests to the end and produce results for all test cases that are
missing reference results. This is convenient when adding new tests, as
it allows one to drop *.re files in the test directory, run the tests
(failure is expected), manually verify the generated results and copy
them to the test directory.
2021-07-17 21:38:36 +01:00
Ulya Trofimovich 88ff1e5a2a run_tests.py: patch newlines and backslashes in test results on windows. 2021-06-27 16:23:28 +01:00
Ulya Trofimovich c581194f7a Properly escape backslashes in the generated file paths.
Add escaping in some previously forgotten cases.

Avoid double escaping (previously this happened for some include files
for which file path was constructed as a concatenaton of an already
escaped directory part and the yet unescaped file path in the include
directive).

This only affects platforms that use backslashes in file paths (such as
Windows).
2021-06-27 16:23:28 +01:00
Ulya Trofimovich ad98410b00 run_tests.py: skip overflow-1 on windows (failing due to small stack). 2021-06-27 16:23:28 +01:00
Ulya Trofimovich ebfd61a3db Rewrite recursion into iteration for stats function.
This helps to avoid overflow on systems with small stack.
2021-06-27 16:23:28 +01:00
Ulya Trofimovich c4be6d05d3 run_tests.py: fix tests on Wine.
This fixes `make wtests` (--wine option to run_tests.py).

A few things were broken:
  - re2c binary should have '.exe' file extension
  - `re2c --version` on wine is rather slow, so drop the 2s timeout
2021-06-27 16:23:28 +01:00
Ulya Trofimovich 0ea48c905e GitHub Actions CI: unmask Windows tests. 2021-06-27 16:23:28 +01:00
Ulya Trofimovich b8a47acfa1 GitHub Actions CI: upload test build directory, not source directory. 2021-06-27 16:23:28 +01:00
Sergei Trofimovich d363c06980 configure.ac: allow user to set non-standard PYTHON
Useful on systems with multiple python implementations.
While at it allow both 'python3' (preferred) and 'python' spellings.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2021-06-24 23:36:05 +01:00
Ulya Trofimovich e7d43c7655 Use unique names for header files generated by the tests.
Header files may be created in the same directory, so that one header
overwrites the other. It also causes races in run_tests.py when it tries
to clean up intermediate files created by each test.
2021-06-22 23:38:46 +01:00
Serghei Iakovlev beb0fe59bb Make remove() function simpler
The previous version of this function has multiple responsibilities and
actually had knowledge for which it was not intended.

These changes are about "S" in SOLID.
2021-06-20 22:24:00 +03:00
Ulya Trofimovich 3e14320a87 run_tests.py: don't shard tests, use chunk size 1.
Previously the script divided all tests into chunks of equal size, which
is suboptimal as different tests take different time, and often large
tests end up in the same chunk. This adds imbalance and makes the test
runner slower than it could be with chunk size 1.

Also, use a more pythonic way to gather results from threads. The old
bash script did that via per-thread log files because it is hard to do
it otherwise in bash. But in python one can simply return results from
each thread, avoiding the overhead on file I/O.
2021-06-20 15:59:38 +01:00
Ulya Trofimovich 75881ab9c6 Remove an old useless test that revealed races in run_tests.py.
The removed test was a trivial modification of another test (with -i
option turned off). It was useful long ago, but not anymore as we have
many tests with or without -i option.

The removed test was problematic because it created a header file with
the same name as the other test, which revealed a race in test runner
that removed the generated header before the other file processed it.

This got uncovered while debugging run_test.py, when I changed
multiprocessing.Pool.map() to multiprocessing.Pool.imap(). The race
happened only once in a few runs.
2021-06-20 15:59:38 +01:00
Serghei Iakovlev 43025a8793 Run regular tests under Windows
These changes are intended to prepare the project to run tests under
Windows.  Currently Windows tests are disabled until we dealing with
failures.
2021-06-20 10:59:58 +01:00
Ulya Trofimovich 60773997a6 Update information about #re2c IRC channels.
After the downfall of freenode #re2c channel has migrated to OFTC and
Libera.Chat.
2021-06-19 21:24:32 +01:00
Serghei Iakovlev 9c9981190b Rewrite re2c test runner in Python
This pull request introduces a completely rewritten test runner
in Python.

The main goals of this change:

- Provide a OS-independent way to run tests (at least using CMake)
- Getting rid of dependence on Unix utilities in tests
  (grep, cat, tr, etc.)
- Flexibility
- Ease of maintenance
2021-06-19 14:20:35 +01:00
Serghei Iakovlev cf57858bce Add step names to benchmark workflow 2021-06-16 00:23:40 +01:00
Ulya Trofimovich 150b2d38b1 benchmarks.yml: quote Python version to prevent parsing it as float. 2021-06-16 00:23:40 +01:00
Ulya Trofimovich 5de6ae6328 run_tests.sh: bring back --keep-tmp-files option.
This reverts commits:
  - ec9eecd077
  - f710983c23

By default if some tests fail, the corresponding temporary files are
kept (for investigation). For the passing tests temporary files are
removed. But in some cases it is convenient to keep temporary files for
the passing tests as well.
2021-06-15 22:49:17 +01:00
Ulya Trofimovich f710983c23 run_tests.sh: remove obsolete '--keep-temp-files' option from help.
Note: the option itself was removed in commit
ec9eecd077, but the obsolete description
remained until now.
2021-06-15 08:51:23 +01:00
Ulya Trofimovich 424dfed352 Submatch Java benchmark: update REgen submodule. 2021-06-15 07:53:22 +01:00
Ulya Trofimovich 3dce73623c Submatch Java benchmark: account for varying RE size within each group.
REgen procduces input data with variable RE size within each group, so
in order to generate truthful plot it is necessary to take that variance
into account.

For JS plot, compute the x-coordinate as the average RE size withing
each group (also average the y-coordinate within each group, as before).

For PGF plot, don't average RE size, instead use individual RE size as
the x-coordinate. Do a few transformations on the benchmark results:
remove outliers using centered moving median, then smooth the curve
using centered moving average.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich ff6382b5bc Submatch Java benchmark: copy JS chart to the build directory.
It is a runtime dependency of ReTdfa.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich 6dbaae39bd Submatch Java benchmark: add a small samples file (zipped). 2021-06-15 07:53:22 +01:00
Ulya Trofimovich f8f10c201a Submatch Java benchmark: add REgen as a Git submodule.
REgen is a program that generates input data for the benchmark. We use a
fork of the original repo in order to be able to apply local patches.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich 82623c3e8c json2pgfplot.py: escape backslash when generating TeX code. 2021-06-15 07:53:22 +01:00
Ulya Trofimovich f70d5a8364 Java submatch benchmark: generate PGF plot. 2021-06-15 07:53:22 +01:00
Ulya Trofimovich 0f63fed70d Submatch DFA AOT benchmark (run script): fail if output file is not set.
Exception is verification mode, when there is no need to log output.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich e60fbdcc8f Submatch DFA JIT benchmark: drop leftmost greedy variants.
Although leftmost greedy results are different from POSIX ones, the
relative difference of register/registerless variants is similar, so
it suffices to keep only the POSIX variants.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich 80b3249e00 Remove the old build script for ReTdfa benchmark. 2021-06-15 07:53:22 +01:00
Ulya Trofimovich a38f46396d GitHub Actions (benchmarks workflow): add ReTdfa benchmark. 2021-06-15 07:53:22 +01:00
Ulya Trofimovich 2c1b39cff0 Add Makefile.am for the ReTdfa benchmark.
The benchmark is built if configure option --enable-benchmarks is set
and environment variable JAVA_HOME is non-empty.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich 9079ce8614 Add CMakeLists.txt for the ReTdfa benchmark.
The benchmark is built if configuration option RE2C_BUILD_BENCHMAKRS has
been set and CMake is able to find Java.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich 25d881dc2a Add regular expression library and benchmark by Angelo Borsotti.
ReTdfa is a Java library that contains a family of algorithms for
regular expression parsing and submatch extraction based on TNFA and
TDFA. It is also a benchmark for various algorithms, including some
that are based on libre2c.

This commit also adds Java bindings to libre2c.
2021-06-15 07:53:22 +01:00
Ulya Trofimovich c15ef2d410 libre2c: don't allocate/free memory for pmatch[] in the library.
This should be done by the user, and the library may only store a
pointer to the allocated memory in the regex_t structure (this is
convenient for the foreign bindings).
2021-06-15 07:53:22 +01:00
Ulya Trofimovich 6fe4df03ae libre2c: do not include project-local headers in regex.h.
The regex.h header is included by the users of the library. Including
other local headers in it is problematic, because the user then has to
specify additional include search paths (and do so by trial and error
rather than by some general rule).

Strictly speaking, this commit breaks C++98 compatibility as <stdint.h>
is non-standard in C++98. But in practice this is unlikely to cause any
problem, as libre2c is a recently added experimental library which
hardly has any users that do not have a C++11 toolchain.
2021-06-15 07:53:22 +01:00
Serghei Iakovlev 4a89dc2d6e Speedup CI workflow by removing not used cache step 2021-06-13 21:13:17 +01:00
Ulya Trofimovich 7f27352602 Better handling of syntax errors in re2c directives.
- Fail with an error in some confusing cases like
  `/*!include:re2c x.re */` that are likely to be unintentional syntax
  errors (double quotes missing around the filename), but previously did
  not fail and were treated like comments (no code was generated).

- Improve error messages for syntax errors such as a bad block name.

AFL tests had to be updated, because the original tests that crashed the
lexer now fail earlier due to an unrelated reason, so a space character
had to be added in some tests to make them hit the same error as before.
2021-05-28 12:16:45 +01:00
Ulya Trofimovich 536f097936 Update docs regarding precedence of special rules in reused blocks. 2021-05-28 00:18:55 +01:00
Ulya Trofimovich 11af1f43c7 Allow overriding special rules inherited from reusable blocks.
Within one block special rules *, $ and <!> cannot be redefined (it is
an error). However, when reusing other blocks it might be convenient to
override inherited special rules with local ones. This commit separates
inherited and local special rules by storing them in separate containers
that are merged at the end.

Also, this commit merges functions that validite and "normalize"
specifications into one function. This has to be done because some of
the validation checks must be performed before merging special rules,
and some must be done after that.
2021-05-28 00:18:55 +01:00
Ulya Trofimovich db641794fd Update documentation and add more examples for reusable blocks. 2021-05-28 00:18:55 +01:00
Ulya Trofimovich 4fff2e35fb Enable reuse blocks by default and deprecate -r, --reusable option.
Now that `/*!rules:re2c ... */` and `/*!use:re2c ... */` blocks can be
mixed freely with the ordinary `/*!re2c ... */` blocks, there is no
reason not to allow reuse mode by default.
2021-05-28 00:18:55 +01:00
Ulya Trofimovich 4f8adcb3cc Clean up data structures that represent reuse blocks.
Also, fix memory leak in the parser (found by LeakSanitizer): don't
forget to free std::string that was allocated to hold block name in the
inline `!use` directive.
2021-05-28 00:18:55 +01:00
Ulya Trofimovich 261a4b91ed Disallow garbage at the end of directives (with a few exceptions).
Historically re2c allows arbitrary text before the closing comment of
the directives such as `/*!ignore:re2c ... */` and `/*!max:re2c ... */`.
It only makes sense for the ignore directive (which is just a multiline
comment), but not for other directives. This commit disallows garbage at
the end of all directives, except `/*!ignore:re2c ... */` and (for the
reasons of backward compatibility) `/*!max:re2c ... */`.
2021-05-28 00:18:55 +01:00
Ulya Trofimovich 2262fe7dbe Don't forget to adjust line count after inline !include directive. 2021-05-28 00:18:55 +01:00
Ulya Trofimovich 7e66ba5334 Add inline !use directive.
The inline `!use:<block-name>;` directive  can be used in the middle of
a re2c block. It allows one to merge a block named <block-name> into the
currect block: rules of the used block are added to the current set of
rules, and configurations are added to the current options. Overlapping
rules and configuraitons have the usual priority, as if the used block
was literally inserted in place of the `!use` directive (the first rule
wins, and the last configuration wins).
2021-05-28 00:18:55 +01:00
Ulya Trofimovich ee37e0f03f Initial implementation of named blocks.
Named blocks allow one to reuse any rules block, not only the last one.
The syntax named blocks extends existing syntax for unnamed blocks:

    /*!rules:re2c:<name>
        ...
    */

An optional name is specified after a semicolon. The block can then be
used by specifying its name in a use block:

    /*!use:re2c:<name>
        ...
    */
2021-05-28 00:18:55 +01:00
Ulya Trofimovich 867cf7522c Update docs and examples for the inline include directive. 2021-05-21 08:55:34 +01:00
Ulya Trofimovich cb6d9025ad Allow include directives in the middle of a block.
This commit addresses issue #351 "include directive limitations",
reported by Henry Harvey.

An include directive in the middle of a block is useful in cases when
the include file contains additional rules overlapping with the rules in
the including file. In such cases the usual directive won't work, as it
would crate a new re2c block with its own set of rules (rather than
merge the included rules into the current set).

The inline directive syntax is slightly different from the usual re2c
directive syntax: comment markers '/*' and '*/' are dropped to avoid
nested multiline (which are unsupported in C/C++), and the ':re2c' part
is also dropped because it is redundant (the inline directive is already
inside of a re2c block).
2021-05-21 08:55:34 +01:00
Ulya Trofimovich db219561ec libre2c: add option REG_AUTOTAGS that enables full parsing mode.
The new option automatically adds tags for all subexpressions, as if
they were wrapped in capturing parentheses. This is only useful for
experimental purposes (to measure parsing speed in the case of fully
tagged RE and study performace degradation of different algorithms as
the density of submatch increases).
2021-05-12 23:39:51 +01:00
Ulya Trofimovich a703a46586 libre2c: use t-string fragments instead of trie for regless algorithms.
Unwinding tag history from its trie representation is rather slow. This
can be done in advance at regcomp() time, and the resulting t-string
fragments can be stored in backlinks (this is what regtstring() already
uses). For offset construction t-string fragments also need to include
negative tags.
2021-05-11 22:43:34 +01:00
Ulya Trofimovich 62fe269e84 libre2c: use common forward pass for all regless-TDFA algorithms.
The forward pass is the same for regexec(), regparse() and regtstring().
2021-05-10 09:12:00 +01:00
Ulya Trofimovich 44611fe7f8 libre2c: add some comments for regparse() and regtstring(). 2021-05-10 09:12:00 +01:00
Ulya Trofimovich 478fe2576a libre2c: add an algorithm that constructs a t-string.
This CL adds a new flag REG_TSTRING and a new API function regtstring()
that returns a t-string (a flattened representation a parse tree where
characters of the input string are interleaved with tags).

The goal of this algorithm is to construct parse results in the cheapest
possible way. There is no standard representation of a parse tree, and
any nontrivial representation would likely incur a significant overhead
(the algorithm would spend most of the time constructing parse results
rather doing the actual parsing).

The t-string representation requires very little effort to construct,
provided that the t-string fragments corresponding to the tagged paths
in the epsilon-closure are prepared in advance at regcomp() time. The
fragments are stored as arrays of tags, so that they can be easily
copied to the resulting t-string. Importantly, this does not require
unwinding of tag history stored in a trie form, which is rather slow.

A t-string is represented as a sequence of 16-bit values that are either
ASCII characters (that occupy the lower byte, leaving the higher byte as
zero) or tags (that are numeric value shifted to the upper half of the
16-bit range).

16-bit size for t-string characters is chosen to align with the
experimental Java implementation by Angelo Borsotti.

T-string allocation is done on the library side, and the t-string is
stored in the regexp structure. The user gets an immutable view of the
resulting t-string and is not expected to free memory after calling
regtstring(). Moreover, the library reuses the same memory on each
regtstring() call and reallocates it only if the new t-string does not
fit into the old memory area.

All in all, the new regtstring() API is primarily intended for
benchmarking the speed of the parsing algorithms, and not for "official"
use.
2021-05-10 09:12:00 +01:00
Ulya Trofimovich 308b434e1d libre2c: add algorithms for submatch extraction on all repetitions.
This patch adds a new flag REG_SUBHIST and new API functions regparse()
and regfreesub().

regparse() returns parse results as an array of nmatch size, where each
element is an array of offset pairs for the correspoinding capturing
group. If a group has matched repeatedly at different parts of the input
string, then its array will contain multiple offset pairs; otherwise, a
single pair. This differs from the standard POSIX API, where onl the
last offset pair for each group is returned.

The allocation of memory for the parse results is done by the library
(the user cannot know how much memory will be needed). The ownership of
parse results is transferred to the user, who is expected to deallocate
memory allocated by regparse() with regfreesub().
2021-05-10 09:12:00 +01:00
Ulya Trofimovich e3d5973eb6 libre2c: don't forget to set fallback tags in regexec_dfa.
In order to do that, it is necessary to compute fallback states and
insert fallback tags.
2021-05-10 09:12:00 +01:00
Alexander Shemetovskiy 58b5e89439 Fix link to CONTRIBUTING.md 2021-04-26 00:00:53 +01:00
Ulya Trofimovich b1d3afe144 Rename directory for SIMPA article. 2021-04-06 07:30:42 +01:00
Ulya Trofimovich 07e417fa94 Fix typo in documentation (add missing space). 2021-04-05 10:25:45 +01:00
Ulya Trofimovich 1ae96895a8 CMake: pass re2c options for benchmark as two distinct arguments.
Otherwise the build fails with error:
    re2c: error: bad long option: --no-generation-date --no-version
2021-04-04 10:18:33 +01:00
Ulya Trofimovich b4efac3cc0 Add benchmark results on April 2, 2021.
The measurements have been taken on an Intel(R) Core(TM) i7-8750H CPU
with 32 KiB L1 Data cache (x6 cores), 32 KiB L1 Instruction cache (x6
cores), 256 KiB L2 Unified cache (x6 cores), 9216 KiB L3 Unified cache,
32 GiB RAM.

Software versions:
- ragel-7.0.4
- kleenex built from Git at commit d474c60
- re2c built from Git at commit 1c3bead
- re2-2020-11-01
- GCC-10.2.0
- Clang-11.0.0
2021-04-02 11:50:50 +01:00
Ulya Trofimovich 1c3bead790 Benchmarks: update ragel to 7.0.4 (and update autogenerated files). 2021-04-02 11:10:51 +01:00
Ulya Trofimovich a13d86491e Benchmarks: create directory for kleenex before building it. 2021-04-02 11:10:51 +01:00
Ulya Trofimovich b55ab37a22 Generate benchmarks with --no-version to avoid updates on every release. 2021-04-01 23:51:20 +01:00
Ulya Trofimovich 042cf6b671 json2pgfplot.py: fix accidentally swapped 'symbols' and 'captures'.
Also, take care of the singular/plural form.
2021-04-01 23:51:20 +01:00
Ulya Trofimovich 116873e30a json2pgfplot.py: use 'fixed relative' number format.
It reduces the visual noise on the plot: there are no exponents, but
the number of printed decimal places depends on the magnitude. In
combination with very high precision and some custom code that rounds
fractional part but keeps integer part intact, this allows one to have
numbers that are not too precise, but not too rounded either.

This format also has the advantage that it does not need math font, so
fonts like Comic Neue that don't have math support can be used as well.
2021-04-01 23:51:20 +01:00
Ulya Trofimovich 1177560f5e json2pgfplot.py: add option --font <comicneue | cmbright>.
The new option allows one to select the font to be used in the generated
PGF plot. Currently the supported fonts are 'comicneue' (Comic Neue) and
'cmbright' (Computer Modern Bright).
2021-04-01 23:51:20 +01:00
Sergei Trofimovich 1b402b0e88 configure.ac: avoid bash-specific '==' comparison
In https://bugs.gentoo.org/779187 Matt noticed errors when running ./configure
on dash:
    ./configure: 5339: test: x: unexpected operator
    ./configure: 5386: test: x: unexpected operator

The change is to use POSIX '=' comparison instead of bash-specific ==.

Patch-by: Matt Whitlock
Bug: https://bugs.gentoo.org/779187
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2021-03-31 22:09:44 +01:00
Ulya Trofimovich 568d4226f7 Move variable initialization before goto statement.
This is to avoid compiler errors on Solaris 10, see #347.
2021-03-29 07:57:50 +01:00
Ulya Trofimovich 342e53a71e Release 2.1.1. 2021-03-27 18:28:33 +00:00
Ulya Trofimovich a609454ebe Update CHANGELOG for release 2.1.1. 2021-03-27 18:23:13 +00:00
Ulya Trofimovich a051e673de Distcheck: test that release tarball can be built with CMake.
This is to prevent bugs like #346 "No CMakelists.txt file in new 2.1
release".
2021-03-27 18:16:32 +00:00
Ulya Trofimovich 27f42a454d Add CMakeLists.txt to release tarballs.
It was accidentally dropeed from EXTRA_DIST in commit
9959efed38. This was reported in #346
"No CMakelists.txt file in new 2.1 release".
2021-03-27 15:05:08 +00:00
Ulya Trofimovich ddae31d386 Release 2.1. 2021-03-26 19:11:47 +00:00
Ulya Trofimovich 9c9bf9decd Move EXTRA_DIST under WITH_BENCHMARKS to fix basic bmake distcheck.
`bmake distcheck` still fails with the same error if configured with
`--enable-benchmarks`, but now at least in the basic configuration it
succeeds. The error with `--enable-benchmarks` is:

  Making distclean in benchmarks/submatch_nfa
  bmake[2]: "[.]/re2c-2.0.3/_build/sub/benchmarks/submatch_nfa/Makefile"
            line 407: Could not find ./.deps/bench_submatch_nfa-bench.Po
  bmake[2]: Fatal errors encountered -- cannot continue
2021-03-26 18:57:52 +00:00
Ulya Trofimovich bf9003445e Update CHANGELOG for release 2.1. 2021-03-26 17:41:37 +00:00
Ulya Trofimovich a8d540d2ef GitHub Actions CI: add -m32 build with GCC on Linux.
A recent commit bf5b965384 fixed an error
specific to build environments which have 32-bit size_t. It was not
captured by CI because the CI didn't use 32-bit builds on Linux/macOS,
and it didn't run tests on Windows (which has 32-bit size_t).
2021-03-26 09:44:53 +00:00
Ulya Trofimovich ecf2d186b7 GitHub Actions: let unused compiler flags default to an empty string. 2021-03-26 09:44:53 +00:00
Ulya Trofimovich 2d78364f02 GitHub Actions CI: remove obsolete workaround for arguments with spaces. 2021-03-26 09:44:53 +00:00
Ulya Trofimovich b0eebb06b4 GitHub Actions CI: fix shell quoting to allow spaces in CMake arguments.
Use printf to quote array elements when expanding them to a string, or
when passing as arguments to CMake.
2021-03-26 09:44:53 +00:00
Ulya Trofimovich 3b933dc360 Add missing include (fixes build error on Fedora). 2021-03-26 09:37:25 +00:00
Ulya Trofimovich bf5b965384 Fix error in 32-bit mode (in fixed tags optimization).
The error was in setting a constant to ~0u and comparing it to another
constant of type size_t, defined as std::numeric_limits<size_t>::max().
In 64-bit mode these are different values, but in 32-bit mode they are
the same, which triggered errors in the algorithm that finds fixed tag
candidates. The error manifested as a lot of broken tests.
2021-03-25 07:36:55 +00:00
Ulya Trofimovich 8e4d8d2431 Remove obsolete build scripts for LSan (it is integrated into ASan). 2021-03-25 07:36:55 +00:00
Ulya Trofimovich f9d5825021 Add missing includes to make header self-contained. 2021-03-25 07:36:55 +00:00
Ulya Trofimovich 8139571a16 Remove similar cases in submatch DFA JIT benchmark. 2021-03-25 07:36:55 +00:00
Ulya Trofimovich 5470d6613f Drop fractional part in timings for submatch DFA AOT benchmarks.
They normally take hundreds of milliseconds to run, so the fractional
part doesn't matter and it clutters the output.
2021-03-25 07:36:55 +00:00
Ulya Trofimovich bcc5674f96 Clean up data generation scripts for submatch DFA AOT benchmarks.
Replace them all with a small python script that copy-pastes small
sample enough times to fill 100M file.
2021-03-25 07:36:55 +00:00
Ulya Trofimovich 5f81b48a80 Rework submatch DFA AOT benchmarks for repetition.
Changes:
  - give benchmarks more descriptive names
  - make the first benchmark triple in the "rep" series use multiple
    tags and the same counters as the other triples
2021-03-25 07:36:55 +00:00
Ulya Trofimovich 85f3bcaea2 Drop Kleenex patch, as the upstream has been fixed. 2021-03-25 07:36:55 +00:00
Ulya Trofimovich 3f0d6cc220 Rename submatch DFA AOT benchmarks (to enforce order and group by name).
Prefix all benchmarks with a number, where the first digit is the group
index (e.g. all "real-world" benchmarks start with 0), and the second
digit is the index of a benchmark inside group. Now it is possible to
run a selected subset of benchmarks, e.g. all "real-world" benchmarks:

  $ ./run.py --filter '^0'
2021-03-25 07:36:55 +00:00
Ulya Trofimovich 6a1666bc29 benchmarks/submatch_dfa_aot/run.py: interpret filters as regexps. 2021-03-25 07:36:54 +00:00
Ulya Trofimovich 3256099620 Rename submatch DFA AOT benchmarks for re2c (to avoid "-bc" suffix).
re2c benchmarks use two different end-of-input handling methods: the
default bounds checking method, and the more recent $-rule method based
on `re2c:eof` configuration. Although it is interesting to compare their
performance, presenting both methods on the plots makes them too
cluttered (and the performance of the two methods is similar compared to
other algorithms and lexer generators). So one of them is chosen as
primary (bounds checking) and its suffix "-bc" is dropped to simplify
labels on the plots.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich 46a2cdeac0 json2pgfplot.py: change --relative option to --relative-to <name>.
The new option requires passing (part of) a name of the algorithm to be
used as a base for normalizing other algorithms.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich 2d626ebe7f json2pgfplot.py: make dots at the end of cropped columns more visible. 2021-03-25 07:36:54 +00:00
Ulya Trofimovich 7e13a453bd json2pgfplot.py: better handling of plot limits.
Don't cut off parts of the plot because of too-small limits: set limits
based on the number of bars in each individual plot, and use "ymax" and
"ymin" to specify exact limits (rather than the previously used
"enlarge y limits" setting).
2021-03-25 07:36:54 +00:00
Ulya Trofimovich 14d8b56dab json2pgfplot.py: choose scale based on the global average and maximum.
Compute maximum bar length ("xmax") based on the global average and
maximum values among all benchmarks. This is to avoid cases when a very
long bar dominates other bars and makes them appear too small. Such
outliers are cropped and marked with "..." to show that they overflow.
Previously the corring was done only in "relative" mode, because in
"absolute" mode it was unclear how to choose "xmax" value. Now that
"xmax" is computed based on global average and maximum, cropping is used
in both "relative" and "absolute" modes.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich 389ad6d086 json2pgfplot.py: optionally plot binary size in addition to CPU time.
Also add binary size plots to benchmarks/submatch_dfa_aot/run.py.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich 2863e5431f json2pgfplot.py: allow JSON input w/o "regsize" and "captures" fields.
For DFA AOT submatch benchmarks we do not know the number of captures or
the regular expression size. In principle they could be extracted from
the generated file (for re2c only), or an option could be added to the
programs to print statistics (for re2c and ragel, but not kleenex, as it
autogenerates the program and the user controls only the regexp). But it
would be still problematic, as different engines have slightly different
regexps and ways to mark submatch positions.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich a6b82aceb0 json2pgfplot.py: use uniform scale regardless of --relative option.
Uniform scale means that there is a global scale (a common maximum value
shared by all benchmarks). Previously this was used only in "relative"
mode, when all algorithms of a given benchmark are normalized by the
first algorithm. Now it is also used in "absolute" mode.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich f5a2515afd Add verification options to benchmarks/submatch_dfa_aot/run.py.
The new options are:
    --verify       verify parse results on full data files
    --quickverify  verify parse results on small data samples

Replace the old verification script verify.sh with run.py.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich 3f969f8726 Rewrite benchmarks/submatch_dfa_aot/run.sh in Python.
Also, add options `--output <JSON file>` (to generate JSON output in a
form accepted by json2pgfplot.py) and `--filter-out <word>` (to mask
some of the benchmarks). The new script run.py can be used as follows:

  $ ./run.py -h
  usage: run.py [-h] [--output OUTPUT] [--filter FILTER]
                [--filter-out FILTER_OUT] repcount

  positional arguments:
    repcount         number of times to run one benchmark

  optional arguments:
    -h, --help       show this help message and exit
    --output OUTPUT  JSON file to write benchmark results to
    --filter FILTER  pattern to select a subset of benchmarks by name
    --filter-out FILTER_OUT
                     pattern to mask a subset of benchmarks by name
2021-03-25 07:36:54 +00:00
Ulya Trofimovich df89452946 json2pgfplot.py: allow intermixing benchmark groups in the input.
Previously the script grouped benchmarks with the same name together
only if they appeared sequentially in the input file, so that all
benchmarks in one group preceded any benchmarks in another group. Now
this restriction is relaxed: benchmarks with the same name are grouped
together regardless of their position.
2021-03-25 07:36:54 +00:00
Ulya Trofimovich eab9cf4347 json2pgfplot.py: add a comment about expected JSON format. 2021-03-25 07:36:54 +00:00
Ulya Trofimovich 5873e77359 Separate compilation and linking steps in submatch_dfa_aot build.
This is needeed for ccache: it only knows how to cache the compilation
of a single file. Other types of compilations (multi-file compilation,
linking, etc) will silently fall back to running the real compiler.
2021-03-25 07:36:54 +00:00
Sergei Trofimovich 99f85ac1ef src/dfa/dead_rules.cc: move semicolon to a new line
Notice d benign warning when built with clang++ -Weverything:

    src/dfa/dead_rules.cc:205:77: warning: for loop has empty body [-Wempty-body]
        for (; sentcls < nsym && sentsym >= dfa.charset[sentcls + 1]; ++sentcls);
                                                                                ^

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2021-03-12 08:47:11 +00:00
Sergei Trofimovich 42d1b66950 src/skeleton/generate_data.cc: avoid 't' local variable shadow
Noticed when built with clang++ -Weverything:

    src/skeleton/generate_data.cc:325:35:
      warning: declaration shadows a local variable [-Wshadow]
                        const mtag_t &t = tagtrie.head[tval];
                                  ^
    src/skeleton/generate_data.cc:300:21:
      note: previous declaration is here
            for (size_t t = ltag; t < htag; ++t) {
                    ^

Renamed `t` to `mt` to disambiguate.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2021-03-12 08:47:11 +00:00
Sergei Trofimovich 45bc776fb7 src/skeleton/mtag_trie.h: avoid stray semicolon
Noticed when built with clang++ -Weverything:

    ./src/skeleton/mtag_trie.h:67:2: warning:
      empty expression statement has no effect;
        remove unnecessary ';' to silence this warning [-Wextra-semi-stmt]
    {;
     ^

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2021-03-12 08:47:11 +00:00
Ulya Trofimovich 1d826f4dc5 libre2c: add registerless TDFA algorithm.
The idea is to replace registers and register operations with a runtime
log of backlinks that allow to reconstruct the matching TNFA path and
unwind tag history backwards from the final state to the initial state.

As the benchmarks show, on artificial inputs registerless TDFA can be
much faster than TDFA with registers (a few orders of magnitude). On
real-world inputs it is slightly slower (up to 2x).
2021-03-07 14:08:29 +00:00
Ulya Trofimovich 0291d3da83 Correct comments about explicit instantiation of C++ templates.
Previosly the comments erroneously referred to it as "explicit
specialization", which is a different thing.
2021-03-07 14:08:29 +00:00
Ulya Trofimovich 047e61f570 libre2c: make regexec_dfa template depending on automaton type.
This is to avoid runtime overhead on checking which type of actions
should be performed (TDFA or staDFA).
2021-03-07 14:08:29 +00:00
Ulya Trofimovich e7887f8f02 Use 32-bit integers instead of bitfields for tag info.
Bit fields allow packing tag index and tag sign together in one 32-bit
value, which saves space. However it makes re2c slower (approximately
10% on benchmark bench_submatch_nfa/HTTP-RFC7230).
2021-03-07 14:08:29 +00:00
Ulya Trofimovich 4c5d4abdb4 Add a python script for converting benchmark results to a PGF plot.
usage: json2pgfplot.py [-h] [--relative] input output

    positional arguments:
      input       input JSON file
      output      output TeX file

    optional arguments:
      -h, --help  show this help message and exit
      --relative  output CPU time relative to the first algorithm
2021-03-07 14:08:29 +00:00
Ulya Trofimovich 5ef0b746dd Use google/benchmark library for NFA and DFA-JIT benchmarks. 2021-03-07 14:08:29 +00:00
Ulya Trofimovich 117268d681 Add documentation for --depfile option. 2021-03-03 21:29:58 +00:00
Ulya Trofimovich 7000b4788a Add tests for the new --depfile option. 2021-03-03 08:38:40 +00:00
Ulya Trofimovich be9c8dad96 run_tests.sh: support generation of depfiles. 2021-03-03 08:37:19 +00:00
Ulya Trofimovich 33d25eed4e Use the right parent file when opening include files.
Parent file is the one that contains `/*!include:re2c*/` directive, and
it is not necessarily the same as the most recently opened file (parent
file may have multiple include directives, in which case the most recent
file may be the sibling include file, not the parent one). The incorrect
behavior was introduced in 777476b0d8.
2021-03-02 08:32:40 +00:00
Ulya Trofimovich a30aa9fabc Use existing file paths (not just basenames) when generating depfile.
This matters when `--depfile` option is used together with `-I` option,
and include files are not in the current directory.
2021-03-02 07:52:43 +00:00
Ulya Trofimovich 3ba9108047 Add option --depfile <filename> to generate build dependency file.
The new option is similar to GCC or Clang option `-MD -MF <filename>`.
It computes a transitive closure of all files included with
`/*!include:re2c ... */` directives and writes them to the specified
file in the form of a makefile rule:

    <output> : <input1> <input2> ...

The new option requires that the output file is specified (otherwise it
is unclear how to generate dependency rule).
2021-03-01 23:04:00 +00:00
Ulya Trofimovich c189eb7d9d Add lzip to the list of distribution tarballs.
Note: currently .lz tarball is slightly smaller than .xz (1.7M vs 1.9M).
2021-01-22 07:27:49 +00:00
Ulya Trofimovich 9959efed38 Fix make dist: add missing EXTRA_DIST files and remove obsolete ones. 2021-01-22 07:26:37 +00:00
Ulya Trofimovich d6b0a6b5a4 Return simple s-tags example in addition to the complex one with YYFILL. 2021-01-15 08:10:22 +00:00
Ulya Trofimovich 0811fdc0fa Update submatch example to show how tags should be handled by YYFILL.
This is to avoid confusion as in bug #341: "Tag positions are
unexpectedly shifted in buffer refill mode".
2021-01-12 08:32:43 +00:00
Ulya Trofimovich 13e90b1061 Github Actions: add a new workflow for benchmarks.
The new workflow runs once a week or when manually triggered.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 3b58d5d635 Always regenerate re2c benchmarks using the built re2c executable.
For other engines (kleenex and ragel) regeneration is optional (it is
controlled by CMake option RE2C_REGEN_BENCHMARKS and Autoconf option
--enable-benchmarks-regenerate). This is so because it may be
problematic to download and build other engines, and the results may
be hard to reproduce.

For re2c, it makes sense to always see the latest result.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 1c4659a2eb Tweak benchmark parameters to fit it into reasonable time. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich b74f285457 Use ls -s instead of stat -c%s in script to make it work on macOS. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich fd5fc93a1a Remove make invocation from bench_submatch_dfa_aot run scripts. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 5fb972f204 Do not enable debug info (-g) for bench_submatch_dfa_aot benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 5907182c35 CMake: rename target 'benchmarks' to 'bench_submatch_dfa_aot'. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 7d8261419b CMake: add 'all' and 'clean' targets for bench_submatch_dfa_aot.
Override default CMake 'clean' target by setting directory properties
CLEAN_NO_CUSTOM (which prevents removal of all outputs of custom
commands) and ADDITIONAL_CLEAN_FILES (which adds selected files to the
'clean' target). Use the combination of these properties to make the
'clean' target remove autogenerated C code, binaries and data files,
but keep generators (kleenex, ragel).
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 7bbc87a8d8 Hardcode benchmark input data as C strings instead of loading from file.
For libre2c benchmarks (bench_submatch_nfa and bench_submatch_dfa_jit)
the input is not large (unlike bench_submatch_dfa_aot), so it is
possible to hardcode it as C strings. This allows to avoid file I/O,
which is problematic because paths to the input files depend on the
relative location of the source and build directories.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 69b330a36f Move benchmarks build files to subdirectories. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 2d6b807e1b Use Automake silent rules for building submatch benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 38ad7d9abd Drop less interesting variants of submatch benchmarks.
- Drop ragel -T1/-F1 variants, as they are always slower than -G2.
- Drop re2c TDFA(1) with --eager-skip option in order to reduce the
  number of re2c variants (the dropped variant is sometimes better,
  sometimes worse than TDFA(1), but not by much, and not worth having
  a separate variant).
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 9c0088add8 Add build option to turn on/off regeneration of C code for benchmarks.
For Autotools, the option is --enable-benchmarks-regenerate.
For CMake, the option is RE2C_REGEN_BENCHMARKS.

If the option is off (the default), C files for benchmarks are copied
from pre-generated files.

If the option is on, C files are generated with regexp engines.
Pre-generated files are updated. This requires building regexp engines
(kleenex, ragel, re2c), which works at the moment but may easily break
in the future, as it depends on downloading source code from the
internet and building it. Ragel is built from a versioned archive and
needs only a C++ compiler, but kleenex is a haskell program which
requires ghc and cabal (and it also needs patching for the recent ghc).
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 9b19eb70b9 Add nested CMakeLists.txt for bench_submatch_dfa_aot. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich d8ebd66cb2 CMake: add option RE2C_BUILD_BENCHMARKS (off by default). 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 563bc71ea2 Wire bench_submatch_dfa_aot in the toplevel Makefile.am. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 8e456032d7 configure.ac: add option --enable-benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 23b4d00fdd Deduplicate construction of regexps and strings between benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 451a69922b Add submatch_dfa_jit benchmark. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 7413d729ac Prepare to add submatch_dfa_jit benchmark: extract common part with submatch_nfa. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich f32dd899ef Rename bench_libre2c binary to bench_submatch_nfa. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 2f2e612fea Rename internal option --dfa to --nested-negative-tags.
Note: this option is not documented because it does not have a
corresponding command-line switch or configuration.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich e64c9d0d24 Inline small functions tcmd_t::iscopy, tcmd_t::isset, tcmd_t::isadd. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 1182f816b3 Submatch benchmarks: add "iter" series.
It consists of 3 independent subseries ("iter_a", "iter_b", "iter_c")
for artificial regexps with submatch extraction under repetition.

"iter_a" is R(n) = (a{n} #t)*.
"iter_b" is R(m,n,k) = ((a{m}|a{n}|a{k}) #t)*.
"iter_b" is R(m,n,k) = (a{m} #t1)* (a{n} #t2)* (a{k} #t3)*.

Ragel generates incorrect parse results on "iter_b" and "iter_c",
because actions collide and either they happen to often, or if
disambiguation operators <: and ** are used, some actions get removed
while they are still needed.

Kleenex generates very large output (tens of megabytes) for "iter_b"
(infeasible to compile with GCC or Clang on O3), and for "iter_c" it
causes OOM condition.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 5792db469d Submatch benchmarks: add rules to build engines into the Makefile. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich f5d0f6a398 Submatch benchmarks: create output directories before running commands. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 4483245c72 Rename directory submatch_engines -> submatch_dfa_aot. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 86048ea305 Move libre2c benchmark into benchmarks subdirectory. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich a693da7a60 Submatch benchmarks: add "alt" series.
These are artificial benchmarks for concatenation of alternatives. The
regular expression is:

    R(n,k) =
        (@t_{1,1} a_1* @t_{1,2} | ... | @t_{1,2k+1} a_k* @t_{1,2k+2})
        ...
        (@t_{n,1} a_1* @t_{n,2} | ... | @t_{n,2k+1} a_k* @t_{n,2k+2})

For example R(2,2) = (@a1 a* @a2 | @b1 b* @b2)(@a3 a* @a4 | @b3 b* @b4).
The benchmark includes cases R(1,2), R(1,4), R(1,8), R(2,2), R(2,4),
R(2,8), R(4,2), R(4,4), R(4,8).

For Ragel to handle these benchmarks correctly it is necessary to use
left-guarded concatenation <:.

The benchmarks show that sta-DFA performance degrades quickly with
growing n and k parameters.

Kleenex size and sta-DFA performance degrade quickly with increasing
level of nondeterminism (the k-parameter).
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 6631e27250 Submatch benchmarks: rename "ab" series to "cat". 2021-01-06 08:15:44 +00:00
Ulya Trofimovich af6dec06dc Submatch benchmarks: add a filter for known failures.
Current known failures are Ragel benchmarks ab2_4, ab2_8, ab4_2, ab4_4,
ab8_2. They have nondeterministic tags that require multiple tag
variables to store different possible tag values (until nondeterminism
is resolved, one of the values is selected, and the rest are discarded).
Ragel's actions are not designed for that: if two actions modify the
same variable, Ragel places them in some order on the same transition,
and the resulting value will be incorrect.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich c70cdf36f5 Submatch benchmarks: add "ab" series.
These are artificial benchmarks for sequences of 'a' and 'b' symbols
with varying degrees of tag nondeterminism. The regular expression is:

    R(n,k) = @a_1 a* @b_1 a{k} b* ... @a_n a* @b_n a{k} b*

For example, R(2,4) = @a_1 a* @b_1 aaaa b* @a_2 a* @b_2 aaaa b*. The
benchmark includes cases R(2,0), R(2,4), R(2,8), R(4,0), R(4,2), R(4,4),
R(8,0), R(8,1), R(8,2).

Some of the benchmarks in this series cannot be handled correctly by
Ragel due to its lack of support for nondeterministic tags.

Kleenex size and sta-DFA performance degrade quickly with increasing
level of nondeterminism (the k-parameter).
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 3638449eab Submatch benchmarks: group results by compiler. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich d430348a69 Submatch benchmarks: add re2c TDFA(0) variants. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 89b1ad9368 Submatch benchmarks: add re2c variants that use end of input rule $.
The split is implemented by providing two sets of include files (one for
the default bounds checking method, and one for the $-rule method) and
passing different include options when building *-bc and *-eof benchmark
variants.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich f25d116ec1 Submatch benchmarks: build re2c with debug. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 4516e12115 Mark YYFILL as inline in submatch benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 27d90f4911 Some general cleanup in submatch benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 56d141ce52 Define benchmark output utils as macros to ensure they are inlined.
This is necessary in order to minimize the difference in benchmark results
caused by compiler inlining decisions.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich dca35afffb Small optimization in output utils for submatch benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 5a8513d56b Rewrite Ragel submatch benchmarks in a form closer to re2c.
Instead of writing the output on transitions, only set pointers, and do the
actual writing when the whole rule matches.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 3b47d629c5 Submatch benchmarks: fail assertion instead of growing m-tag list.
The list is preallocated to have enough space (usually there are not so many
m-tags). The old behavior can be returned with define GROW_MTAG_LIST.
2021-01-06 08:15:44 +00:00
Ulya Trofimovich 76cd586b35 Add HTTP benchmark for submatch engines (RFC7230 variant). 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 636f464be8 Share common data files between submatch benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich d9162ff5ad Add some submatch extraction into the email benchmark. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 6fcefcdb76 Add HTTP benchmark for submatch engines (simple variant). 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 047cff55a4 Support arbitrary delimiter string in Ragel benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 704a7972f2 Use memcpy instead of a raw loop. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich afcc7c1d38 Add .gitignore for submatch engines benchmark. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich affb06d191 Add URI benchmarks for submatch engines (simple and RFC3986 variants). 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 3d9a228df6 Add IPv4 benchmark for submatch engines. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 5773fdf46a Factor out common parts of the benchmarks. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich abe0e78463 Add Clang-compiled benchmark variants. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich 4228d90e21 Add benchmark for submatch-capable engines (re2c, kleenex, ragel). 2021-01-06 08:15:44 +00:00
Ulya Trofimovich b66eea236c Move TDFA benchmark into subdirectory. 2021-01-06 08:15:44 +00:00
Ulya Trofimovich eeb4978e94 CMake: minor tweaks in comments. 2020-12-30 10:26:00 +00:00
Ulya Trofimovich ee6e6d7eb8 CMake: override CMAKE_CXX_FLAGS in MSVC builds.
Previosuly cmake/Re2cCompilerFlags.cmake always prepended C++ compiler
options to CMAKE_CXX_FLAGS to avoid overriding user-defined options
passed on the command line with -DCMAKE_CXX_FLAGS. They would still be
overridden by build-type specific options in CMAKE_CXX_FLAGS_DEBUG,
CMAKE_CXX_FLAGS_RELEASE and so on, but at least if the user didn't set
any build type, then user-defined options would take proprity.

However, in MSVC builds CMake populates CMAKE_CXX_FLAGS with default
options, making it impossible (or just hard) to distinguish between
default and user options. So, for MSVC we override CMAKE_CXX_FLAGS.

This commit also fixes the order of CMAKE_CXX_FLAGS added by
cmake/Re2cCompilerFlags.cmake: previosuly the order was reversed, as
each flag was preopended individually. Now all flags are accumulated in
an intermediate variable, which is prepeded in one go.
2020-12-30 09:56:01 +00:00
Ulya Trofimovich 616f34e588 Use memcpy instead of strcpy to avoid warning about unsafe behavior. 2020-12-29 22:31:49 +00:00
Eldar Zakirov 0f57ca3668 Enable support of C++ exceptions on MSVC builds. 2020-12-29 22:11:56 +00:00
Eldar Zakirov 637a382761 Fix compliation on Windows (using MSVS) 2020-12-29 17:03:06 +00:00
Tim Gates fd84b69666 docs: fix simple typo, otheriwse -> otherwise
There is a small typo in libre2c_old/examples/compare/compare.h.

Should read `otherwise` rather than `otheriwse`.
2020-12-17 13:53:02 +00:00
Ulya Trofimovich 4135d0c05c run_tests.sh: cleanup temporary files for non-failing skeleton tests. 2020-11-10 23:28:39 +00:00
Ulya Trofimovich f31eb82c67 run_tests.sh: handle negative return codes in skeleton tests. 2020-11-10 23:27:38 +00:00
Ulya Trofimovich ec9eecd077 run_tests.sh: drop the unused --keep-tmp-files option. 2020-11-10 21:44:51 +00:00
Ulya Trofimovich 745f6e3969 Suppress header generation for skeleton and dot targets.
-t, --type-header option has always been disabled for these targets,
but the recently added directive `/*!header:re2c:on*/` enforced header
generation even if the header option was disabled. Now it checks the
target as well.
2020-11-10 07:56:53 +00:00
Ulya Trofimovich b8b107a300 Skeleton: use circular lists instead of vectors with wrap iterators.
This has the benefit of using a custom slab allocator for list elements,
as well as a simplified way of iterating through the elements (no need
to check for the end of sequence and wrap the iterator).
2020-11-10 07:56:53 +00:00
Serghei Iakovlev 3d6789449c Speed up the CMake configuration by avoiding unnecessary checks 2020-11-07 20:56:40 +02:00
Sergei Trofimovich 8eb6e5c35a --skeleton: add 'auto_da_alloc' reference around remove()/fopen() comment
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2020-11-07 12:17:08 +00:00
Ulya Trofimovich 50ac133cc0 Skeleton: use large output buffer to speedup file writes.
This patch speeds up skeleton generation for test/bug128.re by ~1.5x.
Note that `setvbuf(buffer, NULL, _IOFBF, 1024 * 1024);` does not achieve
the same effect (it makes no difference on systems where buffering is
already enabled).
2020-11-05 23:46:25 +00:00
Ulya Trofimovich efc92f64ce Skeleton: reorder loops to speedup data generation for *.input files.
Process each subpath of the multipath separately (instead of iterating
on all subpaths in lockstep). This allows to write data in the output
buffer sequentially.
2020-11-05 08:16:30 +00:00
Sergei Trofimovich 8090a1bd30 skeleton: delete '.input' and '.keys' files before overwriting them
At least on ext4 `open(O_TRUNC); write(); close()` works a lot
slower than `unlink(); open(); write(); close()`.

My speculation is that ext4 has to do non-trivial free block
accounting at `close()` time that were freed by `O_TRUNC`.

Before the patch:

```
$ rm 1.c.line8.input 1.c.line8.keys; time ../re2c bug128.re -o 1.c -Si
real    0m3,011s
user    0m2,091s
sys     0m0,907s

$ time ../re2c bug128.re -o 1.c -Si
real    0m9,506s
user    0m1,708s
sys     0m0,946s
```

After the patch:

```
$ rm 1.c.line8.input 1.c.line8.keys;  time ../re2c bug128.re -o 1.c -Si
real    0m3,785s
user    0m2,615s
sys     0m1,152s

$ time ../re2c bug128.re -o 1.c -Si
real    0m3,570s
user    0m2,348s
sys     0m1,205s
```

It's a 3x speedup.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2020-11-04 13:09:02 +00:00
Ulya Trofimovich 70c45d1390 Skeleton: lift allocation of temporary buffer out of hot function. 2020-11-02 23:33:50 +00:00
Ulya Trofimovich f24f3c78d5 Skeleton: avoid the overhead on computing tags if there aren't any. 2020-11-02 22:42:32 +00:00
Ulya Trofimovich 0edb0f2bc7 Add test for sta-DFA with end-of-input rule $.
The test covers commit a9d582f9d2. Before
that commit re2c would either fail with assertion on the added test (if
it was built in debug mode), or generate incorrect code (with missing
tag operations on fallback transitions).
2020-11-01 10:30:25 +00:00
Serghei Iakovlev 067bd8af61 Use CMAKE_BUILD_TYPE for single-config build types only 2020-11-01 01:42:21 +02:00
Serghei Iakovlev 2a566af834 Ignore autogenerated directories and files
Update .gitignore
2020-11-01 01:42:21 +02:00
Serghei Iakovlev 7a8d57a302 Add '.log' extension for auto generated test logs 2020-11-01 01:42:21 +02:00
Ulya Trofimovich a9d582f9d2 Don't loose sta-DFA tag actions in final states or with disabled YYFILL.
Also, be aware of sta-DFA tag actions when constructing tags on fallback
transition and when printing the automaton with --dump-adfa option.

Commit 56e46545b8 moved in-state tag
operations before YYFILL label in case $-rule is used. It erroneously
suppressed the generation of sta-DFA tag actions in final states or in
case of disabled YYFILL. This commit fixes that mistake and reinstates
sta-DFA tag actions in such cases.
2020-10-31 10:25:19 +00:00
Ulya Trofimovich 4a47dedad2 Skeleton: lift allocation of temporary buffers out of hot function. 2020-10-30 23:24:27 +00:00
Ulya Trofimovich 3eab74d9fd Provide default initialize and copy operations for wrap iterator.
Depending on the STL implementation these operations are required for
vectors of wrap iterators (in particular, push_back() method may require
a default assignment operator).
2020-10-30 07:51:56 +00:00
Ulya Trofimovich 80f364ee3a Skeleton: use trie to store m-tag histories.
Previously tag values were stored in vectors (even thought most of the
tags are s-tags and have only one element in the history). For tests
with many tags this represenation was taking too much space and time
spent on vector initialization.

Now all tag values are stored as scalars (32-bit integers). For s-tags
the value is the offset. For m-tags the value is an index in the tag
trie (a prefix tree of tag histories that is encoded in an array). This
representation is faster and takes less space.

This allows to save space that was previously used for storing
intermediate tag values of tag variables as vectors

This partially fixes #331.
2020-10-30 00:05:41 +00:00
Ulya Trofimovich e8cdf1ded5 Skeleton: reorder loops to speedup data generation.
Process each subpath of the multipath separately (instead of iterating on all
subpaths in lockstep) in order to reduce the size of storage used for the
intermediate tag values. Previously the required storage was a matrix of size
M x N, where M is the width of the multipath and N is the maximum tag variable
number (prior to tag optimizations). Matrix elements are vectors, because some
tags are m-tags (they need to record the full history, not just the last value).
Allocating and initializing the matrix takes a long time. Now the required
storage is a vector of length N. The same storage is reused for all subpaths.

This partially fixes #331.
2020-10-30 00:05:28 +00:00
Ulya Trofimovich 56e46545b8 Move in-state tag operations before YYFILL label if $-rule is used.
If $-rule is used the lexer may need to jump to the YYFILL label to
rescan the current input character after YYFILL supplies more input.
This may cause re-application of tag operations if they are generated
after the YYFILL label, which may produce incorrect results for non-
idempotent tag operations.

In-state tag operations are used either with sta-DFA (where all tag
operations are in-state and there are no on-transition operations), or
when operations on all transitions agree and can be hoisted out of
transitions into the state body.
2020-10-25 11:22:46 +00:00
Ulya Trofimovich 68611a57a9 Disallow hoisting non-idempotent operations with end-of-input rule $.
If end-of-input rule $ is used, the lexer may need to rescan the current
input character after a successful return from YYFILL. Therefore any
operations that are hoisted out of transitions into the state body may
be re-applied. This is fine as long as the operations are idempotend
(subsequent application produces the same results).

Skip operation is not idempotent, because it increments the cursor every
time it is applied. This is only a problem with --eager-skip option, as
otherwise skip takes place before YYFILL label.

Tag operations may be idempotent or not, depending on whether the tags
used on the right hand side are also used on the left hand side of some
operations (eg 'x = y; y = z;' is non-idempotent because it overwrites
y).
2020-10-25 10:11:01 +00:00
Ulya Trofimovich f41a597bf5 Rename a few tests according to the options they use. 2020-10-24 19:34:21 +01:00
Ulya Trofimovich 2b363b949c GitHub Actions: run skeleton tests after normal tests in the same build. 2020-10-21 08:08:53 +01:00
Serghei Iakovlev 5ec13d6381 Complete CI implementation using CMake and GitHub Actions 2020-10-21 01:00:56 +03:00
Ulya Trofimovich 016a4b0bf7 Regenerate manpages and help.
This update contains the following changes:
  - help message is reformatted to 80 characters (in commit
    9c203791a5)
  - typo fix (in commit ab5f526a21)
2020-10-20 22:40:39 +01:00
Serghei Iakovlev c93f3efe1f Restructuring Configure and Build jobs on GitHub Actions
This is a planned, intermediate change that prepares the following
things:

- Preparing to use different generators (Xcode, NMake, Ninja)
- Preparing to use rebuild and test documentation. This required
  renaming some steps
- Preparing to build libs
- Preparing to use Autotools
- Preparing to make a full migration of CMake builds from Travis CI

Notable improvements include the unification of the Configure job
(now it is Fast Configure) for all platforms
2020-10-20 15:18:33 +03:00
Serghei Iakovlev 8bfac019e5 Remove rst2man output redirection as it doesn't work on Windows
There is no need for redirect output with > (which doesn't work on
Windows) as this is how rst2man works:

  rst2man [options] [<source> [<destination>]]

For more see: https://github.com/skvadrik/re2c/issues/325
2020-10-20 09:34:51 +03:00
Serghei Iakovlev 0bb8e8711a Rephrase error messages for RE2C_REBUILD_DOCS=ON
This aims to provide a bit more clear error messages on regenerate
manpage stage as well as documentation.
2020-10-20 09:34:51 +03:00
Serghei Iakovlev eb0281382b Check for man and sed on Windows when RE2C_REBUILD_DOCS is ON
Windows does not have a native 'man' and 'sed' commands.
Therefore, we are looking for the Cygwin versions of 'man' and 'sed'.

For more see: https://github.com/skvadrik/re2c/issues/325
2020-10-20 09:34:51 +03:00
Serghei Iakovlev 9c203791a5 Add the ability to generate manpage and documentation for BSD systems
- Stripping headers may not work as expected, as man output differs
  on different systems. This should work now.
- Simplified output parsing procedure by replacing the regular
  expression by TERM=dumb.
- Stripping escape sequences.
- Added documentation about the intentions of this script.

For more see: https://github.com/skvadrik/re2c/issues/325
2020-10-20 09:34:51 +03:00
Serghei Iakovlev 41fc158928 Add contributing guidelines
Added notes regarding bootstrap regeneration
2020-10-19 10:22:53 +03:00
Serghei Iakovlev 7a5892fd91 Drop 'fatal' and 'Msg::fatal' in favor of 'error' and 'Msg::error'
This is aimed to reduce assumptions, workarounds and potential
misunderstandings due to not a completely obvious behavior of
'fatal' function.

For more see discussion on https://github.com/skvadrik/re2c/pull/320
2020-10-17 16:07:49 +03:00
Ulya Trofimovich 26f12d233b Merge pull request #322 from skvadrik/cmake-mkdir
Create output directories for CMake builds with RE2C_REBUILD_LEXERS=yes.
2020-10-17 11:35:16 +01:00
Ulya Trofimovich 787bfcd4fe Create output directories for CMake builds with RE2C_REBUILD_LEXERS=yes.
Fixes the following build scenario:

    $ mkdir stage1 && cd stage1
    $ cmake .. && make
    $ cd .. && mkdir stage2 && cd stage2
    $ cmake .. \
        -DRE2C_REBUILD_LEXERS=yes \
        -DRE2C_FOR_BUILD=$(pwd)/../stage1/re2c && make
2020-10-17 10:50:30 +01:00
Serghei Iakovlev ceb557ecbf Merge pull request #321 from sergeyklay/fix/asan-ubsan-linker-flags
Fixed linker flags for Asan and Ubsan profiles.
2020-10-16 19:49:13 +03:00
Serghei Iakovlev 4d69dd719a Don't add CMAKE_STATIC_LINKER_FLAGS flags to Asan/Ubsan builds
This is a fix for linker flags that were mistakenly added after
discussion at https://github.com/skvadrik/re2c/pull/318.

Although STATIC_LINKER is technically a program for "getting one library
from a bundle of something", it works *completely* differently than
EXE_LINKER and SHARED_LINKER.
2020-10-16 18:46:07 +03:00
Serghei Iakovlev a904ff8855 Merge pull request #319 from sergeyklay/install-re2c
Add minimal install test on GitHub Actions
2020-10-14 10:38:38 +03:00
Serghei Iakovlev 28b4501a3d Add minimal install test on GitHub Actions 2020-10-14 09:50:15 +03:00
Serghei Iakovlev ca1619885c Merge pull request #318 from sergeyklay/custom-build-types-support
Added Asan and Ubsan CMake profiles
2020-10-12 19:43:13 +03:00
Serghei Iakovlev 61dd522509 Use Asan and Ubsan CMake's build types in build scripts 2020-10-12 16:29:02 +03:00
Serghei Iakovlev 94032e3026 Added Asan and Ubsan CMake profiles 2020-10-12 10:35:08 +03:00
Ulya Trofimovich abe84e832a Merge pull request #317 from sergeyklay/github-actions-improvements
GitHub actions improvements
2020-10-10 12:24:21 +01:00
Serghei Iakovlev c90189f9e2 Correct linker's and compiler's flags usage 2020-10-10 13:16:16 +03:00
Serghei Iakovlev af4c59de7f Amended build matrix on GitHub Actions 2020-10-09 19:42:18 +03:00
Serghei Iakovlev ba6c96620c Replace deprecated set-env and add-path commands
See: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
2020-10-09 11:57:02 +03:00
Ulya Trofimovich 8e56ce38af Merge pull request #316 from sergeyklay/compiler-flags
Setting up build type and debug compiler flags
2020-10-08 22:46:48 +01:00
Serghei Iakovlev 461ce54d13 Allow empty build type
For more see: https://github.com/skvadrik/re2c/pull/316
2020-10-08 12:07:19 +03:00
Serghei Iakovlev 3c7694f6c4 Added verbose output about the flags used 2020-10-07 13:31:01 +03:00
Serghei Iakovlev 22014a1380 Don't keep ALLOWABLE_BUILD_TYPES variable in global scope 2020-10-07 11:51:33 +03:00
Serghei Iakovlev d239978d7a Remove redundant build type check 2020-10-07 10:21:55 +03:00
Serghei Iakovlev 2898e41520 Use Release build type by default 2020-10-07 10:14:29 +03:00
Serghei Iakovlev 234351e16b Merge Re2cTryCXXFlag.cmake and Re2cCompilerFlags.cmake 2020-10-07 10:13:47 +03:00
Serghei Iakovlev 1b049fa8a8 Rename CMake lists 2020-10-07 10:11:29 +03:00
Serghei Iakovlev eaf19f948a Setting up build type and debug compiler flags 2020-10-06 10:14:34 +03:00
Ulya Trofimovich c23ed638c9 Merge pull request #315 from sergeyklay/build-type
Add Release build type to the build matrix
2020-10-05 13:55:41 +01:00
Serghei Iakovlev c4547fd71b Add Release build type to the build matrix 2020-10-05 12:09:18 +03:00
Ulya Trofimovich e0483119ef GitHub Actions CI: use common steps with a parameterized "run" script for different platforms. 2020-10-04 23:10:22 +01:00
Ulya Trofimovich 5d8f52bfd5 Merge pull request #314 from zenwerk/master
fix typo
2020-10-03 22:04:59 +01:00
zenwerk ab5f526a21 fix typo 2020-10-04 04:57:22 +09:00
Ulya Trofimovich 9293f2c617 Merge pull request #312 from sergeyklay/fix/find-bison
Cleaned up CMakeLists.txt to use platform independent bison search
2020-10-02 11:36:06 +01:00
Serghei Iakovlev 9ce9bf3fa5 Cleaned up CMakeLists.txt to use platform independent bison search
After discussion in
https://github.com/skvadrik/re2c/pull/311#discussion_r498687041,
I decided to double-check this approach again and made sure that it
actually works.
2020-10-02 13:00:49 +03:00
Ulya Trofimovich fdebdff641 Merge pull request #311 from sergeyklay/windows-support
Add Windows support for GitHub Actions
2020-10-02 10:35:06 +01:00
Serghei Iakovlev b93855e274 Minor CMakeLists.txt cleanup, improved bison search 2020-10-02 12:19:35 +03:00
Serghei Iakovlev a1a97dc2bb Add Windows support for GitHub Actions 2020-10-02 09:27:57 +03:00
Serghei Iakovlev a4ca8b48ff Change find_package to find_program for bison
We do not use the functionality provided by FindBISON e.g. BISON_TARGET and
so on.  All we need below is BISON_EXECUTABLE.  Thus, I replaced find_package
by find_program and set BISON_EXECUTABLE explicitly.  This is also fixes
searching executables on Windows systems.
2020-10-02 09:17:24 +03:00
Ulya Trofimovich 36248bb46a Merge pull request #310 from sergeyklay/macos-support
Add macOS support for GitHub Actions
2020-10-01 22:43:54 +01:00
Serghei Iakovlev 79b1093c65 Add macOS support for GitHub Actions 2020-10-01 22:15:11 +03:00
Ulya Trofimovich 78e2cf1471 Merge pull request #309 from sergeyklay/github-actions-support
Initial support of CI using GitHub Actions
2020-09-28 13:57:07 +01:00
Serghei Iakovlev 95d6b283cd Initial support of CI using GitHub Actions 2020-09-28 09:46:30 +03:00
Ulya Trofimovich 92c68aa08b Update documentation for end of input handling. 2020-09-25 07:42:02 +01:00
Ulya Trofimovich f3deaba0a3 Drop useless configuration in the tests.
The bounds check is generated anyway if EOF rule is used. Configuration
`re2c:yyfill:check = 1;` is redundant.
2020-09-21 08:07:13 +01:00
Ulya Trofimovich 520e5cd433 Disallow using -f, --storable state option if YYFILL is disabled.
-f, --storable-state option should not be used if YYFILL is disabled,
because without YYFILL the interrupt points do not necessarily
correspond to storable state labels (with generic API interrupts can
happen on any API invocation). This may cause subtle bugs when the
lexer is resumed from the wrong program point.
2020-09-17 23:45:03 +01:00
Ulya Trofimovich 6f328bf1fe Rename Go tests, add a script to run them. 2020-09-16 23:56:26 +01:00
Ulya Trofimovich 09b21d38c6 Use a better way to disable YYFILL but keep EOF check in the tests.
Instead of defining YYFILL to always return failure, disable it entirely
with `re2c:yyfill:enable = 0;`, but keep the check with
`re2c:yyfill:check = 1;`. This way re2c does not generate dead code that
invokes YYFILL and always fails.
2020-09-16 23:55:22 +01:00
Ulya Trofimovich f3bb438c27 Use ordinary DFA state for EOF rule instead of a special "yyeof" label. 2020-09-16 07:49:30 +01:00
Ulya Trofimovich a50f2ab452 A few clarifying comments. 2020-09-14 22:49:52 +01:00
Ulya Trofimovich 277f0295fc Fix EOF rule in cases when default rule * is not specified.
Previously EOF rule was added only at the code generation level: if was
neither present as an NFA state, nor in any of the final DFA states.
This doesn't work in case there is a nullable loop and the default rule
is not specified, because the initial state gets merged with other DFA
states, which shouldn't match EOF rule. As a result, EOF rule never
matched.

The fix is to add EOF rule on the regexp level as a match-empty rule "".
2020-09-14 22:09:01 +01:00
Ulya Trofimovich 90e5a237bf Merge pull request #307 from s-yasu/fix-utf8-decode
Fix UTF-8 decode for 4bytes rune
2020-09-14 22:07:51 +01:00
Satoshi Yasushima 30130a7941 Fix UTF-8 decode for 4bytes rune 2020-09-15 00:51:04 +09:00
Satoshi Yasushima ca3a455468 Add test for UTF-8 literals 2020-09-15 00:51:02 +09:00
Ulya Trofimovich ee125dab03 Silence -Wmatch-empty-string on trivial obviously nullable cases. 2020-09-10 23:52:53 +01:00
Ulya Trofimovich 960f881636 Remove unused NFA state kind. 2020-09-10 22:50:47 +01:00
Ulya Trofimovich 42a3a485b1 A few minor corrections in the paper.
- Added "preprint" footnote with a reference to the SPE article.
- Corrected submitted\revised/accepted dates.
- Added DOI.
- Changed bibliography style.
- Updated link to Glenn Fowler's page "An interpretation of the POSIX
  regex standard". It is still accessible from the Wayback Machine, but
  the links are not stable. The new link is to a manually uploded copy
  of the page.
2020-09-06 09:31:13 +01:00
Ulya Trofimovich ec2d4b262c Merge pull request #304 from s-yasu/fix-cmake-command
Fix CMake command from cmake to ${CMAKE_COMMAND}
2020-09-04 21:43:35 +01:00
Satoshi Yasushima d2f05de5e7 Fix CMake command from cmake to ${CMAKE_COMMAND} 2020-09-05 01:15:44 +09:00
Ulya Trofimovich 0265a212fa Small tweak in the docs. 2020-08-27 08:11:19 +01:00
Ulya Trofimovich 010b98d3f5 Better handling of path to include subdirectory in the tests.
The problem with the path to include subdirectory is that the tests
can be run from different places relative to the source directory
(an out-of-tree build can be anywhere). Therefore instead of hardcoding
a few possible locations in the test itself, it is better to use a path
relative to @top_srcdir@ and compute it once for all tests.
2020-08-27 07:56:51 +01:00
Ulya Trofimovich ff4ffb0596 Fix example for in-tree builds.
This example uses include file unicode_categories.re and specifies
paths to include directory using -I option. Since the test can be
run both in in-tree and out-of-tree builds, different include paths
are needed to cover different cases.

In addition it is necessary to disable line directives, otherwise the
unstable path to the include file gets embedded in the output file.
2020-08-27 00:01:52 +01:00
Ulya Trofimovich 54a1946880 Include example of lexing Unicode identifiers in the docs. 2020-08-26 23:36:10 +01:00
Ulya Trofimovich 6c37434641 Add example of lexing Unicode identifiers.
The example uses include file unicode_categories.re. It is a partial
fix for #269 "Add examples of Unicode in the docs".
2020-08-26 07:38:04 +01:00
Ulya Trofimovich 01d6299532 Remove duplicate tests for POSIX capturing groups.
The tests are generated with a Bash script from a list of test cases
that contain a regexp and a string. Some test cases use the same regexp
multiple times with a different string. For the autogenerated tests the
string is not used, so such test cases result in identical tests.

This patch changes the script to check for duplicates. The original set
of test cases remains unchanged and can be run with another script:

    test/posix_captures/.run/__run.sh
2020-08-24 22:08:47 +01:00
Ulya Trofimovich ebf3f3e5f8 libre2c: check if the base tag is negative before shifting fixed tags. 2020-08-23 10:22:43 +01:00
Ulya Trofimovich 0c91e61989 Add documentation for --fixed-tags option. 2020-08-22 09:20:56 +01:00
Ulya Trofimovich 992134f6ff Add fixed-tag optimization for nested tags (part 2).
Many tests have been updated, because some of the variable tags have
been turned into fixed tags.

The following script was used to check that skeleton tests for the new
re2c run without errors on the data (.input and .keys) generated both by
the new re2c and by the old re2c.

  if [ $# -ne 3 ]; then
      echo "usage: $0 <testdir> <re2c_new> <re2c_old>"
      exit 1
  fi

  testdir="$1"
  re2c_new="$2"
  re2c_old="$3"

  for f in `find $testdir -name '*.re'`; do
    echo $f

    # extract options
    opts="$(head -n 2 $f \
        | grep -E -a '^.*INPUT.*$' $f \
        | sed -E 's/.*\$INPUT -o \$OUTPUT(.*)$/\1/')"

    # run skeleton test with new re2c
    $re2c_new --skeleton $opts $f -oa.c && gcc a.c -oa && ./a

    # run skeleton test with new re2c on the data generated by old re2c
    mv a.c b.c
    $re2c_old --skeleton $opts $f -oa.c && gcc b.c -o b && ./b

    # cleanup
    rm -f *.keys *.input a b
  done
2020-08-22 08:59:58 +01:00
Ulya Trofimovich 3783bb0335 Add tests for --fixed-tags option.
Some exisitng tests have been changed to explictly set option
`--fixed-tags toplevel` or `--fixed-tags none`. These tests would be
affected by flipping the default from `toplevel` to `all`, because some
of the variable tags would become fixed, making the whole test useless,
as it no longer tests what it is supposed to test.

For some tests "nofix" variants have been added. Currently the generated
code is the same as for the base variant, but this will change after
flipping the default from `toplevel` to `all`.
2020-08-22 08:59:58 +01:00
Ulya Trofimovich 47cecdc79a Add internal option --fixed-tags <none | all | toplevel>. 2020-08-22 08:59:58 +01:00
Ulya Trofimovich bda07a8cf4 Correctly set final tags that correspond to multiple capturing groups.
With POSIX capturing groups one tag may correspond to multiple capturing
parentheses, as in ((e)). Previously re2c generated assignment chains
like `yypmatch[i] = yypmatch[i+2] = ...` and treated the whole chain as
a single l-value. This doesn't work in cases that are more complex than
a simple assignment, for example with generic API when the shift
distance is nonzero (it is not possible to shift the whole chain of
assignments in one operation).

This patch fixes the broken cases when a tag expands to multiple tags by
setting the first tag (which may require multiple statements or checks),
and then assigning the remaining tags to the first tag.
2020-08-22 08:59:58 +01:00
Ulya Trofimovich 81705b8f13 Add fixed-tag optimization for nested tags (part 1).
When applying fixed tags optimization to tags that are enclosed in
alternative or repetition it is necessary to check if the base tag has a
no-match value (in that case fixed tag should also be set to no-match).
For tags in top-level concatenation the check is not needed, because
they always match.

This commit implements the optimization, but does not enable it yet
(that would require updatimg many test results and will be done in a
separate commit).

This is related to bug #281 "Apply fixed tags optimization more
aggressively".
2020-08-22 08:59:58 +01:00
Ulya Trofimovich 5e16ca05d3 Minor correction of a bug reference in CHANGELOG. 2020-08-22 08:22:58 +01:00
Ulya Trofimovich 23a3a1f532 Release 2.0.3. 2020-08-22 08:12:59 +01:00
Ulya Trofimovich 2b76a87d08 Update CHANGELOG for release 2.0.3. 2020-08-22 08:01:26 +01:00
Ulya Trofimovich 0b87ac7bd4 SIMPA article: final corrections before publication.
- Fixed final state number in the example from 8 to 10.
- Re-worded a few sentences.
2020-08-21 08:22:49 +01:00
Ulya Trofimovich c1b246a8e3 CMake: add an example of building re2c as a subproject. 2020-08-19 22:39:44 +01:00
Ulya Trofimovich e626849408 CMake: move build rules for docs out of conditional branch.
These rules are always needed (e.g. the file help.cc generated by these
commands is one of the source files that are required for the minimal
build). The rules were accidentally moved under conditional branch in
commit be688fdc6d, and were enabled only
if re2c is the root project. This caused a build error "Cannot find
source file" when trying to build re2c as a subproject:

  ├── other
  │   ├── build
  │   └── CMakeLists.txt
  └── re2c

With the following other/CMakeLists.txt:

  project(other)
  add_subdirectory(../re2c re2c-build)

This is a partial fix for #302 "Using CMake add_subdirectory fails".
2020-08-19 22:21:25 +01:00
Ulya Trofimovich 4c97baa591 Release 2.0.2. 2020-08-08 09:04:08 +01:00
Ulya Trofimovich b2e2d75308 Update CHANGELOG for release 2.0.2. 2020-08-08 08:59:44 +01:00
Ulya Trofimovich 8ff0df653e SIMPA article: add link to the reproducible capsule on Code Ocean. 2020-08-08 08:53:56 +01:00
Ulya Trofimovich 157bc8f356 Debug: output minus sign for negative tags with --dump-dfa-tree. 2020-07-31 23:20:40 +01:00
Ulya Trofimovich 77da086ec3 Package CMake files into release tarballs. 2020-07-30 22:08:50 +01:00
Ulya Trofimovich ec654f12cb Enable re2go building by default. 2020-07-30 09:39:26 +01:00
Ulya Trofimovich 0e5443b2d2 Address reviewers' remarks to the artcle for Software Impacts journal.
Added "Impacts" section and more references to projects that use re2c.
2020-07-30 07:28:20 +01:00
Ulya Trofimovich 2072fa1048 Release 2.0.1. 2020-07-29 18:34:16 +01:00
Ulya Trofimovich 9311e5295c Fix release script to update re2c version for CMake. 2020-07-29 18:32:29 +01:00
Ulya Trofimovich 66c8e21495 Add a short article about re2c for the Software Impacts journal. 2020-07-28 23:21:09 +01:00
Ulya Trofimovich a058ba18fc Release 2.0. 2020-07-20 19:25:21 +01:00
Ulya Trofimovich 1a8568e871 Updated CHANGELOG. 2020-07-20 18:55:00 +01:00
Ulya Trofimovich 6261543445 run_tests.sh: fix grep invocation and typo in variable name. 2020-07-20 09:08:00 +01:00
Ulya Trofimovich eb5c63dc7b Merge pull request #298 from trofi/master
run_tests.sh.in: add usage example
2020-07-20 01:17:17 +01:00
Sergei Trofimovich 8198c794ba run_tests.sh.in: add usage example
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2020-07-20 01:02:53 +01:00
Ulya Trofimovich 4da53fc99e Avoid ambiguity in the generated DFA names in the presence of include files.
If the definition of a re2c block comes from an include file, use the name of
the file as well as the block line to generate a unique DFA name. The block
line itself is insufficient as there may be two blocks on the same line in
different files.

This has caused an error in one of the skeleton tests.
2020-07-19 17:24:53 +01:00
Ulya Trofimovich 1f93425fbd Get rid of options in test filenames (part 8).
Rename Unicode tests. Rename is needed because Unicode tests are
clustered into groups of similar tests that have similar filenames,
and the previous rename left one tests of a grop having a short filename
without options, while the remaining tests have options in the filename.

Update test generator and script that runs Unicode tests.
2020-07-19 17:24:53 +01:00
Ulya Trofimovich b853513b47 Get rid of options in test filenames (part 7).
Update test generator for character classes.
2020-07-19 17:24:53 +01:00
Ulya Trofimovich c8fe2104dc Get rid of options in test filenames (part 6).
Rename POSIX submatch tests. Update generator.
2020-07-19 17:24:52 +01:00
Ulya Trofimovich aa0592d99f Replace many tiny tests for flex support with one bit test. 2020-07-19 17:24:52 +01:00
Ulya Trofimovich 1a8a0ce7ca Remove a few not-so-useful skeleton tests. 2020-07-19 17:24:52 +01:00
Ulya Trofimovich 0a55a58461 Rewrite layout tests.
This commit replaces many (~128) autogenerated layout tests with a few
hand-written tests. The autogenerated tests were not very useful as they
covered many similar trivial use cases, and only a few interesting ones.
2020-07-19 17:24:52 +01:00
Ulya Trofimovich 3d2fbb5238 Get rid of options in test filenames (part 5).
Update autogenerator for layout tests.
2020-07-19 17:24:52 +01:00
Ulya Trofimovich ebfefb671f Get rid of options in test filenames (part 4).
Update autogenerator for config tests, rename config tests.
2020-07-19 17:24:52 +01:00
Ulya Trofimovich 390e13b3ff Get rid of options in test filenames (part 3).
Update example filenames in docs and build files, regenerate manpages.
2020-07-19 17:24:52 +01:00
Ulya Trofimovich 277e2c8c8f Get rid of options in test filenames (part 2).
This commit renames test files and patches filename strings embedded in
line directives, warnings, error messages, etc. in the generated output.

When possible, all options have been dropped from the filename. In cases
when this would cause collision due to multiple different tests being
renamed to the same file, only the first test has a filename without
options, and the remaining tests have filenames with options where all
special characters have been replaced with underscores.

Conversion has been done automatically with the following Bash script:

  #!/bin/bash

  for f in `find . -name '*.re'`; do
    stem="$(basename $f | sed -E -e 's/^([^.]+)\..*$/\1/')"
    ext="$(basename $f | grep -q -- '--lang(go)' && echo go || echo c)"
    x="${f%.re}.$ext"
    newf="$(dirname $f)/$stem.re"
    newx="$(dirname $f)/$stem.$ext"

    if [ "$f" == "$newf" ]; then
        continue
    elif [ -e "$newf" ]; then
        sfx="$(basename $f | sed -E -e 's/^([^.]+)[.](.*)[.]re$/\2/' -e 's/[(.+-]+/_/g' -e 's/[)]//g')"
        newf="$(dirname $f)/${stem}_$sfx.re"
        newx="$(dirname $f)/${stem}_$sfx.$ext"
    fi

    a="$(echo $(basename ${f%.re}) | sed -E -e 's/([()])/\\\1/g' -e 's/\./\\./g')"
    b="$(basename ${newf%.re})"
    perl -p -e 's/'"$a"'/'"$b"'/g' "$f" > "$newf"
    perl -p -e 's/'"$a"'/'"$b"'/g' "$x" > "$newx"
    rm "$f" "$x"
  done
2020-07-19 17:24:52 +01:00
Ulya Trofimovich 303ef47837 Get rid of options in test filenames (part 1).
This commit adds a comment with options to the beginning of each .re file.
Because of the added line all test results had to be updated (line numbers
in line directives, error messages, warnings, etc. have increased by one).

The testing script run_test.sh has been changed to use options in the
comments rather than options in the filenames.

Conversion has been done almost automatically (except for a few rare tricky
cases) with the following horrible Bash script:

  #!/bin/bash

  for f in `find . -name '*.re'`; do
    switches=`basename "$f" | sed \
        -e 's/^[^.]*\.re$//g' \
        -e 's/^[^.]*\.\(.*\)\.re$/\1/g' \
        -e 's,[+],/,g' \
        -e 's/^\([^-]\)/-\1/' \
        -e 's/--\([^ (-]*\)/ --\1/g' \
        -e 's/(\([^)]*\))/ \1/g' \
    `
    ext=`basename "$f" | grep -q -- '--lang(go)' && echo go || echo c`
    x="${f%.re}.$ext"
    ff="$f.mod"
    xx="$x.mod"
    linedirs=`egrep -q -- '(#|//)line' "$x" && echo 1 || echo 0`
    dot=`echo "$switches" | fgrep -q -- ' --emit-dot' && echo 1 || echo 0`
    skel=`echo "$switches" | fgrep -q -- ' --skeleton' && echo 1 || echo 0`
    if [ $ext == c ]; then
        l='// re2c $INPUT -o $OUTPUT '"$switches"
    else
        switches=`echo "$switches" | sed 's/ --lang go//'`
        l='//go:generate re2go $INPUT -o $OUTPUT '"$switches"
    fi
    nocomment=0
    if [ "$(tail -n 1 $x | fgrep -q 'error: ' ; echo $?)" -eq 0 ]; then
        nocomment=1
    elif [ $dot -eq 1 ]; then
        nocomment=1
    elif [ $skel -eq 1 ]; then
        nocomment=1
    fi

    echo "$l" > "$ff"
    cat "$f" >> "$ff"
    if [ $linedirs -eq 0 ]; then
        head -n 1 "$x" > "$xx"
        if [ $nocomment -eq 0 ]; then echo "$l" >> "$xx"; fi
        tail -n +2 "$x" >> "$xx"
    else
        head -n  2 "$x" > "$x.head"
        tail -n +3 "$x" > "$x.tail"
        if [ $nocomment -eq 0 ]; then echo "$l" >> "$x.head"; fi
        if [ $ext == c ]; then
            e='s/^([ \t]*#line )([0-9]+)(.*\.re"|.*\.c")$/($1).($2+1).($3)/eg'
        else
            e='s/^(\/\/line ".*".)([0-9]+)$/($1).($2+1)/eg'
        fi
        perl -p -i -e "$e" "$x.tail"
        cat "$x.head" "$x.tail" > "$xx"
        rm "$x.head" "$x.tail"
    fi

    a="$(basename $f | sed -E -e 's/([()])/\\\1/g' -e 's/\./\\./g')"
    perl -p -i -e 's/^(.*'"$a"'[:(])([0-9]+)(.*)$/($1).($2+1).($3)/eg' "$xx"
    perl -p -i -e 's/^(.*shadowed by rule at line )([0-9]+)(.*)$/($1).($2+1).($3)/eg' "$xx"
    perl -p -i -e 's/^(.* already defined at line )([0-9]+)(.*)$/($1).($2+1).($3)/eg' "$xx"
    if [ $skel -eq 1 ]; then
        perl -p -i -e 's/^(.*[_.]line)([0-9]+)(.*)$/($1).($2+1).($3)/eg' "$xx"
    fi
  done

  find . -name '*.re' -o -name '*.c' -o -name '*.go' | xargs rm
  for f in `find . -name '*.mod'` ; do mv "$f" "${f%.mod}" ; done
2020-07-19 17:24:51 +01:00
Ulya Trofimovich 316c02d06f run_tests.sh: clean up auxiliary test files. 2020-07-14 08:09:35 +01:00
Ulya Trofimovich 6dfd2969d3 Makefile.am: remove nonexistent header from the list. 2020-07-14 08:02:25 +01:00
Ulya Trofimovich 14363b90c6 Updated README.md. 2020-07-13 22:56:28 +01:00
Ulya Trofimovich 078d2fded1 Update paths in a testing script. 2020-07-12 18:35:54 +01:00
Ulya Trofimovich eb48666e20 Update .travis.yml to make a second build that rebuilds lexers. 2020-07-12 10:54:02 +01:00
Ulya Trofimovich 967540566b Makefile.am, CMake: simplify bootstrap process.
Re2c is a self-hosting lexer generator, therefore it needs re2c in order
to rebuild itself. It bootstraps using precompiled files in the bootstrap
subdirectory. Precompiled files can be used as long as the .re files are
not changed, otherwise lexers must be regenerated. Previosuly the build
system tried to autodetect whether to regenerate or to copy bootstrap
files by checking if the re2c executable exists in the build directory.

However, for the build system it means that dependency graph is changed
on every build, because bootstrap commands and regenerate commands have
different dependencies: bootstrap commands depend on the bootstrap
files, and regenerate commands depend on the .re files. It is not
possible to choose the commands statically, because the check for re2c
executable should run on every build rather than once at configure time.
CMake used a workaround and set both bootstrap and .re files as
dependencies for both commands, which caused weird rebuilds on Travis CI
(when the same lexer was regenerated multiple times during one build).
Automake used a different workaround (a pattern rule that didn't have
the dependency on bootstrap files at all).

This commit disables the checking mechanism and requires passing an
explicit configure parameter and a path to the re2c executable in order
to regenerate lexers. Otherwise, by default lexers are copied from
bootstrap files.

CMake:       cmake ...  -DRE2C_REBUILD_LEXERS=on -DRE2C_FOR_BUILD=<path>
Makefile.am: configure ... --enable-lexers RE2C_FOR_BUILD=<path>
2020-07-12 10:54:02 +01:00
Ulya Trofimovich f025279f98 CMake: require version 3.12 or higher.
CMakeLists.txt uses features such as HOMEPAGE_URL parameter in project()
command and add_compile_definitions() command that were introduced in
CMake version 3.12.

This fixes bug #297 "configure error on ubuntu 18.04 / cmake 3.10".
2020-07-12 08:44:24 +01:00
Ulya Trofimovich 4c0391e2cf Update docs (reorder and rewrite a few sections). 2020-07-10 22:50:45 +01:00
Ulya Trofimovich f811f03006 Use correct options for the first normal block in reuse mode.
Normal blocks should use global options that are accumulated over all
non-reuse blocks, and use blocks should use options of the preceding
rules block, plus the options added by the use block itself. Before
this commit re2c failed to set up global options correctly, and as a
result the first normal block had incorrect options if it was preceded
by some reuse blocks.
2020-07-07 23:29:54 +01:00
Ulya Trofimovich 2a9c122e67 Allow to use normal (non-conditional) blocks in -c mode.
This fixes issue #296 "Conditions required for all lexers when using
'-c' option" reported by Joshua Inscoe.
2020-07-07 23:28:26 +01:00
Ulya Trofimovich a1ebb2e111 Generate condition switch in every re2c block.
Previously in condition mode re2c generated condition switch only for
the first re2c block in the file. This makes it impossible to have
multiple re2c blocks with conditions. The change in this commit doesn't
break backwards compatibility, because the case that was previously
supported (with one lexer per file) works in the same way as before,
and the previously unsupported case (with multiple lexers) now works.

This fixes bug #295 "Condition switch generated for only one lexer per
file" reported by Joshua Inscoe.
2020-07-06 07:58:51 +01:00
Ulya Trofimovich 4a91b65917 Add examples of include files for C and Go backends. 2020-07-05 19:03:24 +01:00
Ulya Trofimovich fc0f73e31c Update tests for reuse mode (move common configurations to rules blocks). 2020-07-05 12:03:06 +01:00
Ulya Trofimovich b7e62a1341 Do not reset API-related configurations in each use:re2c block.
This change breaks backwards compatibility for some (rare) use cases.

For historical reasons re2c reset all API-related configurations to
default values in each `/*!use:re2c ... */` block. This behaviour is
illogical and inconvenient: the whole purpose of reuse mode is to share
configurations, definitions and rules between blocks, and resetting
selected configurations means that they have to be redefined in each
reuse block. This has caused confusion (see bug #291 "Defines in rules
block are not propagated to use blocks" reported by Joshua Inscoe).

The odd behavior was kept for backwards compatibility. It goes back to
the versions of re2c and was probably introduced accidentally or by
mistake. It is unlikely that many users rely on the old behavior: if
they need user-defined configurations in some of the blocks and default
configurations in other blocks, it is more likely that they would
explicitly reset them to defaults rather than rely on undocumented re2c
behavior.

The change affects the following configurations:

    re2c:define:YYGETCONDITION
    re2c:define:YYSETCONDITION
    re2c:define:YYFILL
    re2c:define:YYGETSTATE
    re2c:define:YYSETSTATE
    re2c:define:YYBACKUP
    re2c:define:YYBACKUPCTX
    re2c:define:YYCONDTYPE
    re2c:define:YYCTXMARKER
    re2c:define:YYCTYPE
    re2c:define:YYCURSOR
    re2c:define:YYDEBUG
    re2c:define:YYLESSTNAN
    re2c:define:YYLIMIT
    re2c:define:YYMARKER
    re2c:define:YYPEEK
    re2c:define:YYRESTORE
    re2c:define:YYRESTORECTX
    re2c:define:YYRESTORETAG
    re2c:define:YYSTAGN
    re2c:define:YYSTAGP
    re2c:define:YYMTAGN
    re2c:define:YYMTAGP
    re2c:define:YYSHIFT
    re2c:define:YYSHIFTSTAG
    re2c:define:YYSHIFTMTAG
    re2c:define:YYSKIP
    re2c:label:yyFillLabel
    re2c:label:yyNext
    re2c:variable:yyaccept
    re2c:variable:yybm
    re2c:variable:yych
    re2c:variable:yyctable
    re2c:variable:yytarget
2020-07-05 10:11:43 +01:00
Ulya Trofimovich 09ef30b634 Don't loose "diverge" bit when setting options with custom handlers.
Whenever an option is set or unset by the user, re2c needs to remember
that user-defined options have been updated and have diverged from the
real options. Any following attempt to read options must trigger
synchronization of user-defined and real options. Previously this was
handled correctly for all options except those with custom handlers.
2020-07-05 09:59:33 +01:00
Ulya Trofimovich 6b477d25a2 Merge pull request #293 from trofi/master
.travis.yml: split build commands into individual entries
2020-07-04 20:46:17 +01:00
Sergei Trofimovich 3daf44f304 .travis.yml: split build commands into individual entries
This should allow travis CI measure individual times on each step

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2020-07-04 19:51:07 +01:00
Ulya Trofimovich 374c4a7e32 Add header examples for C and Go to the manpage. 2020-07-04 19:20:50 +01:00
Ulya Trofimovich 6a6c7e092a CMake, Makefile.am: add generation scripts to the dependencies of make docs. 2020-07-04 18:25:35 +01:00
Ulya Trofimovich baa843cfe2 Merge pull request #292 from ryandesign/oldcompilers
Fix for old compilers like gcc 4.2 and clang 3.4
2020-07-04 18:13:46 +01:00
Ryan Schmidt fe285f03d5 Fix for old compilers like gcc 4.2 and clang 3.4
Fixes the build for old compilers that can't deduce const overload for
rend.

Similar to previous problem reported in #198.
2020-07-04 08:36:54 -05:00
Ulya Trofimovich e2f29c1691 Update scripts that run examples to handle autogenerated headers.
The run_tests.sh script generates output for all examples and appends
the generated header at the end of the output file (to make it easier to
diff actual and expected output). Script that run examples from
autogenerated output need to cut off the appended header, otherwise the
example won't compile/run.
2020-07-04 10:39:45 +01:00
Ulya Trofimovich dc0df494c6 Remove re2c:flags:output and make re2c:flags:type-header relative to the output directory.
Before this patch the filename specified in `re2c:flags:t`,
`re2c:flags:type-header` configuration was relative to the directory
of the source file. It is inconvenient for out-of-tree builds, when the
output is generated in a directory different from the source directory
(which may be read-only). Therefore this patch makes the filename in
configuration relative to the directory of the output file.

As for the `re2c:flags:o`, `re2c:flags:output` configuration, it is
removed altogether. Making it relative to the source directory has the
same problems as with the header file, and making it absolute or
relative to the build directory (where re2c is run) is also bad,
because build-related information will have to be hard-coded in the
source file. Given that this is a relatively new configuraion and it
hasn't been documented in any released version of re2c, it is better to
delete it.

The change does not affect `-t`, `--type-header` and `-o`, `--output`
command-line options.
2020-07-04 09:54:54 +01:00
Ulya Trofimovich 0b0622ce54 Add examples of header file generation for C and Go. 2020-07-04 08:34:16 +01:00
Ulya Trofimovich 33417a1119 Paper: address editor remarks (add affiliation and cite figures). 2020-07-03 23:15:40 +01:00
Ulya Trofimovich 56a5dadecf Lexer: make header name relative to the lexer source file.
This fixes build error for in-tree builds wit hlexer regeneration,
broken after recent commit 5d130e89cc
that made filenames in configurations relative to the directory of the
source file.
2020-07-03 23:12:17 +01:00
Ulya Trofimovich 3b5a4ac4b6 run_tests.sh: do not copy each test into temporary subdirectory before running.
Previously we did this to avoid tracking all the files generated by a
test run (optional header files, skeleton artifacts, etc.) However, this
approach has problems with tests that generate header in a nested
subdirectory: directory structure needs to exist (otherwise re2c won't
be able to open the header file), but re-creating it in a temporary
subdirectory is problematic (`find` collides with other threads running
in parallel, creating and removing directories).

Instead of using a sandbox, track all files generated by a test (that
turns out to be not so difficult with shell globs).

This patch adds a requirement that all tests that use header must
specify it explicitly in the test options (in filename) using the long
option --type-header. Also, this patch allows using plus sign in the
argument to --type-header option to substitute for slash (that cannot be
used in filenames). This allows one to specify headers in nested
subdirectories.
2020-07-03 22:22:09 +01:00
Ulya Trofimovich 5d130e89cc Make filenames in configurations relative to the source file directory.
Prepend source file directory to these filenames when parsing
configurations and updating the corresponding options.

The affected configurations are:
    `re2c:flags:o`, `re2c:flags:output`
    `re2c:flags:t`, `re2c:flags:type-header`

The reason for this change is to make the contents of the source files
independent of the subdirectory where they are located relative to the
build directory where re2c is run. Otherwise it is necessary to hardcode
the relative path in the configuration and change it every time when
either the source file is moved to another subdirectory, or the build
directory is changed.

This change breaks backwards compatibility. However, the configurations
have been added not very long ago (in re2c-1.2) and not documented yet,
so it is likely that not many users will be affected. The corresponding
command-line options `-o`, `--output` and `-t`, `--type-header` remain
unchanged.
2020-07-03 22:20:46 +01:00
Ulya Trofimovich 6704dcef5a Extend fixed tags optimization for the case of fixed-counter repetition.
Previosly RE like `@t "xxx"` that use manual repetition were optimized,
but RE like `@t "x"{3}` that use fixed repetition counters were not,
even though they are unrolled to the same RE.
2020-06-30 23:14:16 +01:00
Ulya Trofimovich 7af9d3383a Make go generate comments in Go examples less cryptic. 2020-06-30 08:07:40 +01:00
Ulya Trofimovich d0c3b256e3 Make docs more Go-friendly. Add conditions example. 2020-06-30 08:07:40 +01:00
Ulya Trofimovich 27f7b3506c Add introductory example to the manpages. 2020-06-30 08:07:40 +01:00
Ulya Trofimovich b4f65a723e Use pregenerated output for running gotest on Go examples. 2020-06-29 22:14:20 +01:00
Ulya Trofimovich 77900c2805 Update introductory examples for C and Go. 2020-06-29 22:14:20 +01:00
Ulya Trofimovich be688fdc6d Add manpage for re2go (generated from the same source, but with Go examples).
Go manpage should be generated and installed only if the Go backend is
enabled. Both CMake and Autotools build systems take care of that.
2020-06-28 23:01:41 +01:00
Ulya Trofimovich 37d8966037 Rename C examples: add --lang(c) option to the filenames.
This is needed to unify C and Go example names (to be used in scripts).
2020-06-28 22:58:39 +01:00
Ulya Trofimovich accc5a2046 Get rid of accidental option duplication in a test filename. 2020-06-28 16:47:38 +01:00
Ulya Trofimovich 1ab43f38b1 Fix the way help message is generated, update its bootstrap file.
Changes:
- Use MANPAGER instead of PAGER (no significant difference).
- Set MANWIDTH=100 and to get deterministic line width.
- Tweak genhelp.sh as it was cutting off too many lines in the generated
  output (presumably something has changed in the way man works).
2020-06-28 10:54:21 +01:00
Ulya Trofimovich fa36ff5589 Move C examples into subdirectory. Update paths in build files, tests and docs.
Changes in the generated test output are trivial (file paths in line
directives and warnings).
2020-06-28 10:37:31 +01:00
Ulya Trofimovich 7432c2af07 Add examples for the Go backend. 2020-06-28 10:21:23 +01:00
Ulya Trofimovich 5033918f1e Avoid duplicate EOF labels with conditions.
Include condition name in the name of the label.
The issue was reported Joshua Inscoe.
2020-06-27 21:25:08 +01:00
Ulya Trofimovich 8d854c87f3 Update docs for user interface and configurations.
Changes:

- Added new generic API primitives:
    YYSHIFT
    YYSHIFTSTAG
    YYSHIFTMTAG

- Added new configurations:
    re2c:api:style
    re2c:api:sigil

- Rewrote the "user interface" section.

- Reordered configuraions and API primitives (grouped them by their
  meaning instead of sorting alphabetically).
2020-06-26 22:25:05 +01:00
Ulya Trofimovich 25de893b6a CMake: fix dependencies of docs target and clean up its build rules. 2020-06-23 22:50:57 +01:00
Ulya Trofimovich ae668ea69c Document --case-ranges option and re2c:flags:case-ranges configuration. 2020-06-23 22:49:49 +01:00
Ulya Trofimovich bb0d1973bf Paper: address reviewer's comments on 2nd review.
Changed IRE notation from expressions with operators like (i,J,e_1|e_2)
to more explicit Alt(i,J,e_1,e_2) to avoid confusion around the fact that
e_1|e_2 is neither an IRE nor a RE, but only a part of syntactic form.
2020-06-21 18:36:13 +01:00
Ulya Trofimovich cb11abb3d4 Add code generation option --case-ranges.
The new option defaults to false. Also, add a corresponding boolean
configuration `re2c:flags:case-ranges = 0;`.

The new option allows to generate compact cases of the form
`case low ... high:` in switch statements. This is not standard C/C++
syntax, but some compilers (GCC, Clang, Tcc) support it.

This implements #290 "use switch range" suggested by algorithm314.
2020-06-19 22:39:34 +01:00
Ulya Trofimovich dcdab01320 Small clarifying comment to the argsubst function. 2020-06-19 00:08:33 +01:00
Ulya Trofimovich cb1eae4db9 Merge pull request #289 from trofi/master
autogen.sh: always attempt to create m4/ directory
2020-06-19 00:08:18 +01:00
Sergei Trofimovich 29932c4c7e autogen.sh: always attempt to create m4/ directory
On a fresh checkout `autogen.sh` complains about missing `m4`:

```
$ ./autogen.sh
aclocal-1.16: warning: couldn't open directory 'm4': No such file or directory
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'build-aux'.
...
```

The change always attempts to create the directory.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2020-06-19 00:06:37 +01:00
Ulya Trofimovich 87eef41c1a Fix GCC-10 warning -Wreturn-local-addr.
Previously the function was not erroneous, because only the head of the
newly constructed list was in a local stack variable, and the rest
consisted of reordered elements from the input list. The offending
pointer was initially set to the head of the list (local addr), and
then advanced to subsequent elements. The case when it was not advanced
and still pointed at the local variable was handled in a special way by
returning NULL.

This patch slightly rewrites topsort to use the output parameter
instead of a local variable as the head of the new topsorted list.
2020-06-17 23:09:01 +01:00
Ulya Trofimovich 2293b32c85 Fix Clang warning -Wunused-template. 2020-06-17 22:15:45 +01:00
Ulya Trofimovich dc0e4869f0 Don't bother resetting selected options for the DOT backend.
These options are unused anyway, and the list is not properly updated.
Restructure code to avoid Clang warning -Wimplicit-fallthrough.
2020-06-17 22:08:27 +01:00
Ulya Trofimovich 68139306fd CMake: fix misspelled name in macro definition.
The typo in the macro name resulted in not using re2 library in libre2c
benchmark, even though it was found by CMake. The error was revealed by
Clang warning -Wunused-const-variable.
2020-06-17 08:08:21 +01:00
Ulya Trofimovich 18f80c62b7 Fix some of Clang warnings -Wunused-macro. 2020-06-17 07:41:17 +01:00
Ulya Trofimovich 4230f5f5a1 Fix Clang warning -Wunused-function. 2020-06-17 07:36:32 +01:00
Ulya Trofimovich bbd7fa2068 Fix Clang warning -Wshadow. 2020-06-17 07:30:18 +01:00
Ulya Trofimovich 4c12c4f121 Remove accidentally committed files. 2020-06-17 07:26:46 +01:00
Ulya Trofimovich 0cb1caa3e5 Fix Clang warning -Wunused-value. 2020-06-17 07:19:42 +01:00
Ulya Trofimovich a3c743556d Fix Clang warning -Wmismatched-tags. 2020-06-17 07:15:57 +01:00
Ulya Trofimovich 00623ce0b1 CMake: get rid of redundant local variables. 2020-06-16 22:26:58 +01:00
Ulya Trofimovich fa53e63b12 Move build scripts to subdirectory. 2020-06-16 22:17:59 +01:00
Ulya Trofimovich fd3bdc2e2f CMake: avoid generating ver_to_vernum.cc multiple times.
Build it into a separate CMake object library in order to have one
target that is a dependency of all other targets.
2020-06-16 21:54:37 +01:00
Ulya Trofimovich 8e1913685b CMake: build autogenerated sources once and before everything else.
This patch fixes builds whn both options -DRE2C_BUILD_RE2GO and
-DRE2C_REBUILD_DOCS are set (previously in that case help.cc would be
generated twice, which caused a race and resulted in garbage output).

The desired behaviour is analogous of Automake BUILT_SOURCES. Buld all
autogenerated sources into an object library, and make that library a
dependency of the main target. Note that custom target that depends on
the autogenerated sources can't be used instead (although it may seem
the right solution at first), because somehow it triggers building of
its dependencies multiple, which ruins parallel builds.
2020-06-16 08:06:41 +01:00
Ulya Trofimovich bb525fec00 Build a standalone executable re2go (same as re2c --lang go).
For CMake this is turned on with `-DRE2C_BUILD_RE2GO`.
For Autotools this is enables with `--enable-golang`.
2020-06-15 22:15:50 +01:00
Ulya Trofimovich 0b44c9991b Rename decorate->api:style, placeholder->api:sigil.
These configurations haven't been released or documanted yet, so it is
safe to rename them.
2020-06-14 10:39:09 +01:00
Ulya Trofimovich e87f231052 Add a script to run Go test programs. 2020-06-12 22:42:56 +01:00
Ulya Trofimovich 67bba2c099 Fix skeleton to handle EOF rule.
Previously configuration `re2c:eof` was reset to default in skeleton
mode, resulting in a re2c error "EOF rule is used, but `re2c:eof` is
not set". Since re2c errors are not failures in skeleton tests (some
tests do actually test re2c errors), such cases increased the number
of "expected re2c errors", but did not show up as failed tests.

This patch increases the number of tests that run successfully with
--skeleton by some 28 test cases.
2020-06-12 22:21:26 +01:00
Ulya Trofimovich 4a94769fd5 Report the number of ran tests and soft/hard failures in run_tests.sh.
Soft failures are needed for skeleton tests: in some cases re2c fails to
set correct configurations and the test results in a re2c error, which
is not a hard error (because some tests do test re2c errors).
2020-06-12 18:21:59 +01:00
Ulya Trofimovich 5ce3368c4b Fix accidentally forgotten yyeofrule label prefixes to yyeof.
The generated code had `yyeofrule` labels, but jumps to `yyeof` labels,
so the program would not compile. This inconsistency was introduced in
commit 4253577f47.
2020-06-12 07:09:17 +01:00
Ulya Trofimovich 8d87a97de8 Don't generate space between API name and opening parenthesis.
Changes in the tests are numerous, but trivial (this can be verified
with changing `diff` to `diff -w` in run_tests.sh: given an option to
ingnore all space changes, diff finds no difference and all tests pass).
2020-06-11 23:52:44 +01:00
Ulya Trofimovich d769f57106 Simplify code generation of final tag operations. 2020-06-11 23:26:01 +01:00
Ulya Trofimovich d403262300 Add helper function for tag "copy" operation. 2020-06-11 22:56:44 +01:00
Ulya Trofimovich 64b7c1b4f7 Reuse the same helper function for all "shift" operations. 2020-06-11 22:56:44 +01:00
Ulya Trofimovich 0eb4da6728 Deduplicate code for "context restore" operation into a helper function. 2020-06-11 22:56:15 +01:00
Ulya Trofimovich b53cca5c11 Use a more elegant way to traverse reversed tag history. 2020-06-11 22:54:40 +01:00
Ulya Trofimovich 77078075d1 Deduplicate code for tag operations into helper functions. 2020-06-11 22:54:07 +01:00
Ulya Trofimovich 80a35ce79a Fix erroneous reference binding to null pointer.
Reported by ubsan:
    runtime error: reference binding to null pointer of type 'const struct Tag'

There was no actual crash, as the bound null value wasn't used.
2020-06-10 23:28:23 +01:00
Ulya Trofimovich 3c8cab9459 Add named placeholders in interpolated configuration strings.
Previously re2c allowed to use @@ or a custom string as a placeholder
for an argument in API primitives. With the addition of multi-argument
APIs like YYSHIFTSTAG and YYSHIFTMTAG this has become ambiguous. The
first attempt to resolve ambiguity was to use @@1, @@2, etc. This works,
but it is not perfect for two reasons. First, it is not clear how to
handle multi-digit suffixes: @@12 can be @1 followed by symbol 2, or it
can be @12 (but it is unlikely that re2c will ever have and API with 12
arguments, so it is most likely an error). Second, it is hard to
remember what is the meaning of each numbered placeholder.

This commit adds named placeholders of the form @@{name}. For APIs that
have only one argument short form @@ is still recognized (if the longer
form failed), but for multi-argument APIs only named form is allowed.

It is possible to globally override @@ with any string, for example to
have placeholders of the form ${name} or #{name}.
2020-06-10 23:14:04 +01:00
Ulya Trofimovich 92cbf8fb76 Add generic API for fixed tags.
List of changes:

- Generic APIs YYSHIFT, YYSHIFTSTAG, YYSHIFTMTAG have been added.

- Generic APIs YYSTAGPD, YYMTAGPD have been removed. They were needed
  for STADFA operations, which are now expressed using YYSTAGP /
  YYSHIFTSTAG and YYMTAGP / YYSHIFTMTAG.

- Test results for tests that use generic API have been updated. Some
  variable tags have turned into fixed tags. Tests with fixed-length
  trailing context that do not use tags are no longer erroneous. All
  skeleton tests now need to define new API primitives. STADFA tests
  that use mtags now use YYMTAGP / YYSHIFTMTAG instead of YYMTAGPD.
  Golang test with `re2c:decorate = 1;` that used tags in a hacky way
  via pointers has been removed, because fixed tags cannot be handled
  (and there is a better alternative with `re2c:decorate = 0;`).
2020-06-10 23:03:29 +01:00
Ulya Trofimovich e40d830dcf Merge pull request #287 from trofi/master
configure.ac: store auxiliary configure files in build-aux/
2020-06-07 14:39:26 +01:00
Sergei Trofimovich d63af41a55 configure.ac: store auxiliary configure files in build-aux/
This makes root directory less cluttered. Autoconf-specific
scripts like 'config.guess'. 'install-sh' and friends
are moved to build-aux/ now.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2020-06-07 14:27:26 +01:00
Ulya Trofimovich 7cbec86cdb Update fixed-length trailing context before tags fixed on cursor.
This fixes bug #286 "Incorrect submatch values with fixed-length
trailing context.". The bug was introduced in commit
a27e6e232f.
2020-06-06 14:20:43 +01:00
Ulya Trofimovich 48b0c8fa2b Fix the use of API primitives in code generation of tag actions.
Changes:
- Allow defining YYMTAGP / YYMTAGN / YYMTAGPD with default API. These
  primitives have no sensible defaults, so they always have to be
  defined by the user.
- Don't generate semicolons with `re2c:decorate = 0;`.
- Generate semicolons in certain cases when they were missing.
- Add a TODO about generic API primitives for fixed tags.
2020-06-04 07:16:52 +01:00
Ulya Trofimovich 4253577f47 Use yyeof label prefix instead of yyeofrule.
Previously `yyeof` prefix was used for YYFILL labels in EOF rule mode,
but now they always use `yyFillLabel` prefix, so the shorter `yyeof`
is available for use in the EOF rule final state.
2020-06-02 23:39:57 +01:00
Ulya Trofimovich e6d16189a4 Further simplify YYFILL code generation. 2020-06-02 23:31:15 +01:00
Ulya Trofimovich e4a9119dc6 Don't output space between YYFILL and the opening parenthesis. 2020-06-02 22:51:51 +01:00
Ulya Trofimovich a9ba9fbf6c Deduplicate YYFILL generation code with and without EOF rule. 2020-06-02 22:45:13 +01:00
Ulya Trofimovich c2656e8135 Deduplicate YYSETSTATE generation code with and without EOF rule. 2020-05-31 22:55:32 +01:00
Ulya Trofimovich cef7dd594b Don't generate redundant semicolons after statements.
With `re2c:decorate = 1;` there should be no semicolon, as the user
should be able to fully control the generated text. With Go backend
there should be no semicolon because it is useless.
2020-05-31 21:08:26 +01:00
Ulya Trofimovich 8c7480da04 Makefile.am: fix dependencies of target docs.
Documentation depends on examples, but the build rule was not properly
updated after examples have been updated.
2020-05-31 18:45:42 +01:00
Ulya Trofimovich 45e9363018 Don't emit YYFILL check when the if body is empty. 2020-05-31 18:33:50 +01:00
Ulya Trofimovich 6ffc3ea15e Update examples, add a script to compile and run them. 2020-05-31 18:15:49 +01:00
Ulya Trofimovich ec82927f18 Test the generated output for documentation examples. 2020-05-31 18:02:37 +01:00
Tony Finch e9764de355 Add a C preprocessor lexer to the tests.
Signed-off-by: Tony Finch <dot@dotat.at>
2020-05-31 16:35:43 +01:00
Ulya Trofimovich c7f27e2e9c Move tests to subdirectory where they belong. 2020-05-27 07:52:41 +01:00
Ulya Trofimovich e61b71eabb Small cleanup in options handling code.
- Transform a few methods into functions to prevent accidental change
  of class members (a function can accept parameters as read-only, or
  not have them passed at all).

- Add methods `reset_<X>` for all options and use them.

- Add comments clarifying that user-defined options and default flags
  should not be modified by the "fix" function.

- Reorder a few blocks in the "fix" function (no functional changes).

- Add a helper function for encodings.
2020-05-27 00:12:18 +01:00
Ulya Trofimovich 130a23706f Clean up re2c:startlabel configuration, add autogenerated tests.
This patch maked the following changes to code generation:

- Ensure that string `re2c:startlabel` configuration takes priority over
  boolean `re2c:startlabel` configuration (this preserves the behavior
  of previous re2c versions).

- In `-c` mode, if start label is forced, emit it only for the first
  condition. For other conditions it's useless, as they already have
  `yyc_<condition>` labels. Besides, numerical start labels would have
  unstable numbers, and text start labels would have the same name for
  different conditions (duplicate labels is an error).

Some tests have been removed as they are covered by the newly added
autogenerated tests.
2020-05-25 10:47:39 +01:00
Ulya Trofimovich ab45b5e3de Get rid of useless label increment.
For historic reasons in `-c` mode re2c started label enumeration from 1
rather than 0. Label 0 is reserved for the start state with `-f` option,
or if the start label is explicitly set with `re2c:startlabel`
configuration. In other cases there is no reason to skip index 0 (except
to avoid changes in the generated code). This patch makes a small change
in the code and drops the artificial increment.

The changes in tests are trivial: label numbers have been decreased
by 1 (or by 2, 4, etc. in tests with multiple reuse blocks). The
following perl script decrements all labels in the code generated by
re2c before the change (old.c) and compares the result (old1.c) with the
new code (new.c). The expected diff is empty. This doesn't work for all
tests (e.g. reuse mode), but in most cases it is enough to verify that
nothing else has changed:

    perl -pe 's/(yy|YYDEBUG\()(\d+)/($1).($2-1)/eg' old.c > old1.c
    diff old1.c new.c
2020-05-24 21:44:59 +01:00
Ulya Trofimovich 9e4299ee7d Decouple start label and initial label.
Start label is needed in `-f` mode: it points to state 0 (the beginning
of block, before condition dispatch in `-c` mode). Initial label points
to the beginning of the DFA (after condition dispatch in `-c` mode).
Previously re2c reused the same label in cases when both start and
initial labels were needed and could be placed adjacent to each other.
Aliasing made it difficult to change the code, because changes of the
start label affected the initial label (and caused massive diffs in the
tests due to a shift in the label numbers).

This patch decouples the labels: now start label, if needed, has its own
label, and initial label always has it own label.

There are 29 changed tests. The changes can be grouped in 3 categories:

1. Trivial renumbering of labels. In most cases all labels except `yy0`
   (which is the start label) have been shifted by 1. It is possible to
   mechanically ensure that nothing else has changed using this script:

    for f in `find . -name '*.orig'`; do
        sed -r 's/(.*)(yy)([1-9][0-9]*)(.*)/cat << EOF\n\1\2$((\3 + 1))\4\nEOF/ge' $f > $f.mod
    done

   In most cases the ".mod" file (which is generated from the original
   test result by incrementing all labels with sed) is identical to the
   new tests result. In some cases manual verfication is necessary
   because labels shifted by a varying number (e.g. due to multiple
   reuse blocks in one file: shift was 2 for the first block, 4 for the
   second block, etc.).

2. Flip of adjacent user-defined start label and re2c-defined start
   label. This happened because previously re2c-defined start label
   aliased to the initial label (which is emitted after the user-defined
   start label), and re2c generated the the initial label (the start
   label was hidden). Now there is no alias, and start label is no
   longer hidden. The change is harmless because user-defined start
   label and re2c-defined start label are always generated next to each
   other.

3. Added jump from the start label to the initial label. Previosly the
   state dispatch jumped directly to the initial label, and now it jumps
   to the start label, and from there to the initial label. The extra
   jump should be trivial to optimise for the compiler.
2020-05-24 10:44:09 +01:00
Ulya Trofimovich f1173a92bf Generate start label for each reuse block in storable state mode.
With `-f` each reuse block has its own state dispatch, and it needs its
own start label as well. Previously the initial state dispatch always
used label 0 (the start label of the first block), which is incorrect
for all but the first blocks.

This partially fixes #282 "Options -f, -c and -r do not combine well".
2020-05-23 12:44:20 +01:00
Ulya Trofimovich a4f799b1b0 Enable reuse mode for autogenerated tests that use storable state.
Previously the combination of `-r` and `-f` could not be used because
the generated code was inconsistent at least (or even incorrect). Now
that the combination has been fixed, it can be used for tests.
2020-05-23 00:08:07 +01:00
Ulya Trofimovich 8d16e96965 Backup and restore default flags together with options.
This partially fixes #282 "Options -f, -c and -r do not combine well".
2020-05-23 00:07:56 +01:00
Ulya Trofimovich 8f8d71e310 Generate non-overlapping YYFILL labels for reuse blocks.
Since all reuse blocks have their own enumeration of YYFILL states
starting from zero and their own state dispatch (not shared with other
blocks, as in the case of non-reuse blocks), YYFILL labels in reuse
blocks have identical indices. This patch adds block ID infix to such
labels in order to prevent label collision if blocks are located in
the same function.

This partially fixes #282 "Options -f, -c and -r do not combine well".
2020-05-23 00:07:45 +01:00
Ulya Trofimovich a7542f2b1e Do not accumulate options from rules/reuse blocks in whole-program options.
This is necessary for consistency with YYFILL states (`-f` option),
which are block-local in reuse mode (`-r` option).

Re2c only recently started to allow mixing reuse and normal blocks,
and the primary user was re2c own lexer, so this change is unlikely
to break anyone.

This partially fixes #282 "Options -f, -c and -r do not combine well".
2020-05-23 00:07:35 +01:00
Ulya Trofimovich c9e69e00c9 Keep track of block-local YYFILL state information.
In `-f`, `--storable-state` mode re2c accumulates information about
YYFILL labels and fallback transitions (for EOF rule). For non-reuse
blocks this whole-program information is used to generate one common
state dispatch. Reuse blocks are handled differently: they have each
their own state dispatch, and YYFILL label numbers starting form zero.

Previously re2c incorrectly handled reuse blocks: instead of using
block-local list of states it used the list from the last block. This
patch fixes it.

This partially fixes #282 "Options -f, -c and -r do not combine well".
2020-05-23 00:07:24 +01:00
Ulya Trofimovich 217158707e In reuse mode, use block-local options instead of last block options.
Last block options are used as "global" or "final" options in certain
cases for code generation: namely, when generating state dispatch and
condition enum, which are accumulated over all blocks. In reuse mode,
however, state dispatch is generated in every block, so it should use
block-local options.

This partially fixes #282 "Options -f, -c and -r do not combine well".
2020-05-23 00:05:36 +01:00
Ulya Trofimovich 292a8b0579 Use reuse mode in test generator for configurations.
Exception: don't reuse mode for tests that set `-f` option and
check `YYGETSTATE` and initial state dispatch, as this mode is
broken (re2c always uses configurations of the last block).
2020-05-21 22:36:59 +01:00
Ulya Trofimovich a4ae442448 Add tests for re2c:placeholder configuration.
Rework test generator for re2c configurations.

Also, don't reset options `re2c:decorate` and `re2c:placeholder` to
defaults (the latter is necessary in order to make the new tests pass).
2020-05-21 07:15:58 +01:00
Ulya Trofimovich 8bbce1be59 Add configuration re2c:placeholder.
This is an umbrella option for options like `define:YYFILL@len`,
`define:YYSETCONDITION@cond`, `define:YYSETSTATE@state` etc.

Default value is "@@".
2020-05-19 22:44:38 +01:00
Ulya Trofimovich 5ecfafc277 Go backend: add conditions support (fix generation of conditions enum). 2020-05-19 21:29:59 +01:00
Ulya Trofimovich 19329aea47 Respect re2c:decorate when generating code for trailing context. 2020-05-19 21:16:36 +01:00
Ulya Trofimovich 674f33c0a6 Go backend: add a test for m-tags (slices and trie implementations). 2020-05-19 00:04:41 +01:00
Ulya Trofimovich 8a56d105c2 Go backend: reformat the "generated by" comment to match guidelines.
The correct form (suggested by `go help generate`) is:
    ^// Code generated .* DO NOT EDIT\.$
2020-05-18 22:30:55 +01:00
Ulya Trofimovich 58c2955d0e Go backend: add a test for posix captures. 2020-05-18 21:51:16 +01:00
Ulya Trofimovich 0143f11e4d Go backend: add a test for Unicode encodings and reuse mode. 2020-05-17 23:16:48 +01:00
Ulya Trofimovich 7330c4aca6 Go backend: emit an error if -g, --computed-gotos option is set. 2020-05-17 22:03:58 +01:00
Ulya Trofimovich cd87899c4f Go backend: support -b, --bit-vectors option. 2020-05-17 21:55:35 +01:00
Ulya Trofimovich 2e23583345 Add an alias for generating a newline. 2020-05-17 10:26:41 +01:00
Ulya Trofimovich 089ec8b5a5 Do not add hoisted tags to fallback transitions.
A precondition to hoisting tag operations out of conditional branches
is that all transitions agree on tags, including the potential fallback
(final or default) transition. Therefore tag operations should not be
repeated on fallback transition. With s-tags repeating is redundant but
harmless, but with m-tags it could cause incorrect submatch results.
2020-05-17 09:45:50 +01:00
Ulya Trofimovich 16d26c378e Inline fallback transitions in state dispatch (to avoid jumping to nested blocks).
Previously with the combination of -f, --storable-state option and EOF
rule re2c generated `yyeof<k>` labels in the default branch of each
state. These labels were used as `goto` targets in the initial state
dispatch. Since Golang does not support jumps into nested blocks, this
patch removes `yyeof<k>` labels and inlines the corresponding fallback
transitions into the state dispatch.
2020-05-17 09:44:42 +01:00
Ulya Trofimovich 9b24f33077 Don't reserve usused initial label for skeleton programs.
This was a weird special case in order to preserve code generation
results during the major rework of the code generation subsystem. It is
no longer needed, as the changes in tests are trivial, concern only a
few skeleton tests and can be checked manually (they are caused by a
shift in label numbers).
2020-05-16 10:38:23 +01:00
Ulya Trofimovich 37a9c4c87a Clean up code generation of default case in switch statements. 2020-05-16 10:08:05 +01:00
Ulya Trofimovich 62ffb97b16 Render switch statements more uniformly.
`switch` statements occur in a few contexts in re2c output: switch on
input symbol, initial switch on conditions (with -c), initial switch on
state (with -f), switch on `yyaccept`. Previously different cases were
rendered in a slightly different way (some cases on the same line, some
on a new line; differences in spaces/tabs).

Now all `switch` statements are rendered uniformly (each case on a new
line), except for switch on input symbol which is unchanged (each cases
on the same line except for cases that contain multiline statements
like tag operations, skip with --eager-skip, or YYFILL with EOF rule).
It would be too difficult to change them, as they constitute the larger
part of re2c output. Also, this would make the generated code less
readable (one-line cases look condensed and aligned).

Massive changes in tests are trivial.
2020-05-16 09:23:28 +01:00
Ulya Trofimovich a67ead3c96 Simplify code generation for switch on yyaccept. 2020-05-16 00:00:36 +01:00
Ulya Trofimovich 750a9aae78 Clean up goto elision. Apply it more aggressively with EOF rule.
Previously goto elision was implemented by passing a null target state
instead of the actual DFA state to the code generation function. However
that prevented goto elision in some other cases with EOF rule, because
the decision whether to elide or not was based on the target state
(which was force-set to null).

This patch adds an explicit "elide" flag instead of the null "hint".
2020-05-15 23:39:49 +01:00
Ulya Trofimovich 1df2b53617 Use proper if statement for code generation of state dispatch. 2020-05-15 07:22:34 +01:00
Ulya Trofimovich 453ca516d6 Go backend: add test for YYFILL (without EOF rule) combined with -f.
The combination of YYFILL with EOF rule and `-f` remains a problem due
to the Go limitation: the language disallows jumping into inner blocks
(re2c generates `yyeof<N>` labels inside of conditional branches).
2020-05-15 07:22:15 +01:00
Ulya Trofimovich fd0b415076 Rework autogenerated tests for options related to API decorations.
Also, forbid using EOF rule with `re2c:yyfill:check = 0;`, as this
combination doesn't make sense (with EOF rule the check is necessary
to distingush sentinel symbol from EOF). Previously this configuration
was not supported (the check was generated despite the option).

The new tests are less uniform than the old tests: some of them contain
multiple blocks (when it is necessary to check the effect of previous
block settings on the next block), and some of them consist of multiple
files with a single block (when the tested part of the generated code
appears once per file, not once per block).

The new tests cover more cases: they add EOF rule and `re2c:decorate`,
`re2c:yyfill:check` configurations, as well as new combinations of
previously tested options.

All test cases are generated using one Haskell script.
2020-05-13 23:43:07 +01:00
Ulya Trofimovich 71f0c9825b Align default value of 're2c:*:naked' options with 're2c:decorate'.
Now instead of always defaulting to false, 're2c:*:naked' options
default to the value of 're2c:decorate' (unless they are explicitly set
by the user). The idea behind this change is to allow the user set one
option instead of a dozen, while still allowing a more fine-grained
control if necessary.
2020-05-10 18:29:55 +01:00
Ulya Trofimovich 7e865ffec8 Add static cast to silence '-Wsign-compare' warning with -m32. 2020-05-10 10:25:48 +01:00
Ulya Trofimovich 30e32a47f7 Add static cast to silence '-Wformat' warning with -m32. 2020-05-10 10:24:41 +01:00
Ulya Trofimovich 25e091912a Go backend: change default options (set generic API, unset decorations).
It is necessary to have different sets of default mutable options for
different language backends. For example, all Go programs need to set
generic API, so it makes sense to set it by default.

The difficulty in changing default mutable options based on the constant
(global) options is that re2c allows to intermix mutable and constant
options on the command line. Therefore by the time all constant options
have been parsed, some of the mutable options may have already been set.
It is impossible to tell which of them have been set from the option
values, because a user-set value may coincide with the default value.
Therefore this commit adds boolean flags indicating if a mutable option
has been explicitly set.
2020-05-10 10:05:06 +01:00
Ulya Trofimovich 9d827a9db0 Add configuration 're2c:decorate'.
Also, add more tests for the Go backend that exercise the new option.
Update existing Go tests.

The new configuration has boolean values (zero is false, non-zero is
true). The default value is true. It is mostly useful with generic API.
It decides whether to generate decorations (e.g. parentheses "()") after
the invocation of YYPEEK, YYSKIP, etc. By setting 're2c:decorate = 0;'
it is possible to avoid functional style calls and generate more
free-form code for API primitives.

In the future this is meant to be an umbrella configuration for various
existing "re2c:define:X:naked" configurations.
2020-05-09 10:26:18 +01:00
Ulya Trofimovich 1e6e0fc08d Go backend: add a test for 'yyaccept'. 2020-05-08 15:15:56 +01:00
Ulya Trofimovich f54a858b42 Go backend: add a test for buffer refill without EOF rule.
Also, update the test for buffer refill with EOF rule.
2020-05-08 12:03:58 +01:00
Ulya Trofimovich e129c218d1 Go backend: generate valid YYMAXFILL and YYMAXNMATCH definitions (as variables). 2020-05-07 23:23:39 +01:00
Ulya Trofimovich deeac885da Clean up code generation related to the input API.
One changed test is caused by correctly generating delayed skip
statement, which opens up new possibilities for combine pass.
2020-05-07 07:56:50 +01:00
Ulya Trofimovich 309e602035 Go backend: don't generate semicolon after statements. 2020-05-06 22:55:22 +01:00
Ulya Trofimovich 3b74518466 Fixed error in YYMAXNMATCH usage example in the docs.
Reported by Konstantin Sobolev.
2020-05-05 23:18:58 +01:00
Ulya Trofimovich b4f0a703b2 Clean up bitmap code generation.
Changes in the tests are trivial (despite large diffs). They are caused
by removal of redundant curly braces and one extra level of indentation
(previously generated in order to reduce the scope of bitmap
declaration, but useless because there are zero bitmaps in this case).
2020-05-05 23:11:03 +01:00
Ulya Trofimovich 653b584602 Rename files and merge a few small headers into one. 2020-05-03 22:56:02 +01:00
Ulya Trofimovich 385e9686dc Rename files. 2020-05-03 11:15:59 +01:00
Ulya Trofimovich 82bfdc03f4 Merge a few headers into one. 2020-05-03 11:15:47 +01:00
Ulya Trofimovich 0a313152f8 Rename a few code generation primitives, clean up redundant structs. 2020-05-03 09:53:51 +01:00
Ulya Trofimovich 1cc7d457c3 Port code generation for goto statements on the new output subsystem. 2020-05-03 09:13:05 +01:00
Ulya Trofimovich 9bb515e737 Add missing fallback states with EOF rule.
When EOF rule is used, a final state may be a fallback state even if
all outgoing paths from it are accepting, because the possibility of
YYFILL failure cretes additional default quasi-transition.
2020-05-01 23:39:52 +01:00
Ulya Trofimovich e6fd8997cd Split transform code generation pass into expand and combine passes.
The "expand" pass generates code for stubs: parts of the code that
cannot be generated during the first code generation pass, because they
require some information that only becomes available after the full
program has been generated.

The "combine" pass folds sequences of simple skip/peek/backup statements
into complex statements. For example, it transforms two-statement
sequence 'yych = *YYCURSOR; ++YYCURSOR;' into 'yych = *YYCURSOR++;'.

Also, render yyeof<N> labels properly (without indentation) and don't
generate an empty statement after them unless they are at the end of a
block.
2020-05-01 20:53:27 +01:00
Ulya Trofimovich fbb2deb395 Delay code generation for labels until the full program is constructed. 2020-05-01 20:53:27 +01:00
Ulya Trofimovich abaeec3dc0 Reuse yyfillLable<N> labels with EOF rule.
Previously labels of the form yyfillLable<N> were used only with -f,
--storable-state option. With EOF rule re2c generated label names
with underscores (unless -f was also enabled). Now re2c always uses
labels of the form yyfillLable<N>.
2020-05-01 20:53:27 +01:00
Ulya Trofimovich 4567a8ae5a Store used label flag in the label struct. 2020-05-01 20:53:07 +01:00
Ulya Trofimovich 0d6edd9f2e Add forgotten header include. 2020-04-27 07:56:37 +01:00
Ulya Trofimovich 50c81ccff3 Move code transformation functions to a separate file. 2020-04-27 07:54:21 +01:00
Ulya Trofimovich 60373d7f26 Move code rendering functions to a separate file. 2020-04-27 07:29:31 +01:00
Ulya Trofimovich 65f79ef715 Rename a few types and functions. 2020-04-26 11:18:23 +01:00
Ulya Trofimovich 554a86496b Remove trivial typedef. 2020-04-26 10:37:41 +01:00
Ulya Trofimovich 9d00c7cbeb Renamed type Code to SemAct to avoid name clash with code generation types. 2020-04-26 00:52:11 +01:00
Ulya Trofimovich 0125650e1d Use generic type and functions for various lists in code generation. 2020-04-26 00:22:57 +01:00
Ulya Trofimovich 7e116ac1eb Avoid using complex expressions in function arguments.
Although the current behavior was ok (only one of the arguments was
a complex expression, and it didn't rely on side-effects), such code
patterns are error-prone and may cause subtle bugs in the future.

Note:

Re2c uses C++98 standard. C++11 adds some guarantees in section 1.9.15:
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf):

  Every evaluation in the calling function (including other function
  calls) that is not otherwise specifically sequenced before or after
  the execution of the body of the called function is indeterminately
  sequenced with respect to the execution of the called function.

And a footnote:

  In other words, function executions do not interleave with each other.

But it is does not solve the problem of possible side-effects.
2020-04-25 21:28:21 +01:00
Ulya Trofimovich 1cb46010c3 Add code generation primitives for functions (used in skeleton). 2020-04-25 10:23:28 +01:00
Ulya Trofimovich 2bf3fdf571 Reuse "raw" code statement kind for DOT code generation. 2020-04-24 00:17:18 +01:00
Ulya Trofimovich 89be91f3df Rewrite recursion into iteration (estimation of NFA size for RE).
This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Partial fix for #219 "overflow-1.re test fails on system with small stack".
2020-04-23 23:02:21 +01:00
Ulya Trofimovich 4d9c809355 Rewrite recursion into iteration (nullable RE).
This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Partial fix for #219 "overflow-1.re test fails on system with small stack".
2020-04-23 22:16:51 +01:00
Ulya Trofimovich 7b5643476b Rewrite recursion into iteration (fixed tags computation).
This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Partial fix for #219 "overflow-1.re test fails on system with small stack".
2020-04-22 22:37:24 +01:00
Ulya Trofimovich fd634998f8 Rewrite recursion into iteration (Tarjan's SCC algorithm and YYFILL states).
This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Stack overflow reported by Agostino Sarubbo.
Related to #219 "overflow-1.re test fails on system with small stack".
2020-04-21 23:04:51 +01:00
Ulya Trofimovich 637d4e4688 Rewrite recursion into iteration (paths for -Wundefined-control-flow).
This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Stack overflow reported by Agostino Sarubbo.
2020-04-19 22:48:09 +01:00
Ulya Trofimovich e3e43bcbb7 Rewrite recursion into iteration (skeleton max path length computation).
Ensured that the new algorithm computes the same length as the old one
by adding temporary debug print of the computed length to both
algorithms and verifying that it coincides.

This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Stack overflow reported by Agostino Sarubbo.
2020-04-19 10:48:47 +01:00
Ulya Trofimovich 7b689f4231 CMake: force colored compiler messages with -fdiagnostics-color=always. 2020-04-19 09:07:24 +01:00
Ulya Trofimovich f39b522cd4 Rewrite recursion into iteration (insertion of negative tags in RE).
This is to avoid stack overflow on large RE (especially on instrumented
builds that have larger stack frames, like AddressSanitizer).

Stack overflow reported by Agostino Sarubbo.
2020-04-18 19:33:22 +01:00
Ulya Trofimovich 5f19bee152 Travis CI: add skeleton tests, use Debug -O2 instead of RelWithDebInfo for CMake.
RelWithDebInfo build type disables asserts, which is bad for testing.
2020-04-18 11:07:58 +01:00
Ulya Trofimovich 38034eabe5 Give an explicit error if skeleton is used with non-C language backend. 2020-04-18 10:11:19 +01:00
Ulya Trofimovich 6189985225 Skip skeleton tests for non-C language backends.
Currently --skeleton option can only generate a C program, other
languages (such as Go) are not supported.
2020-04-18 10:00:01 +01:00
Ulya Trofimovich 1503a74509 Use block number in EOF label.
This allows to use EOF rule with multiple blocks in the same function
(previously re2c generated duplicate EOF labels, so the code did not
compile).

This fixes bug #280: "EOF rules with multiple blocks", reported by brk.
2020-04-18 09:19:02 +01:00
Ulya Trofimovich b85dac9676 CMake build scripts: use Debug -O2 instead of RelWithDebInfo build flavor.
RelWithDebInfo keeps debug information, but also sets NDEBUG, which
disables asserts. For development, it is necessary to enable
optimizations, debug info and asserts (and also the additional debug
checks enabled with RE2C_DEBUG).
2020-04-17 23:40:15 +01:00
Ulya Trofimovich c4603ba5ce Fix crash in lexer refill (reported by Agostino Sarubbo).
The crash happened in a rare case of a very long lexeme that doen't fit
into the buffer, forcing buffer reallocation.

The crash was caused by an incorrect calculation of the shift offset
(it was smaller than necessary). As a consequence, the data from buffer
start and up to the beginning of the current lexeme was not discarded
(as it should have been), resulting in less free space for new data than
expected.
2020-04-17 22:47:14 +01:00
Ulya Trofimovich 187fff3a8b Use 'cc' instead of @CC@ for host C compiler in skeleton tests.
CMake and Autoconf do not agree on the name of the variable: CMake uses
CMAKE_C_COMPILER, and Autoconf uses CC. Plain 'cc' doesn't work on systems
that do not have this alias, but it is unlikely that somenone will run
skeleton tests on such systems.
2020-04-17 21:02:55 +01:00
Ulya Trofimovich d6875dff2d Use new output representation for skeleton code generation. 2020-04-17 07:31:55 +01:00
Ulya Trofimovich 8da6666e4b Add forgotten header include. 2020-04-15 07:59:23 +01:00
Ulya Trofimovich 9565237bec Merge remote-tracking branch 'origin/golang-backend' 2020-04-15 07:51:06 +01:00
Ulya Trofimovich 14c5bea658 Total rewrite of the code generation subsystem.
Previously the output program was represented as a list of blocks (one
block per each re2c comment in the source file). Each block consisted
of a list of heterogenous fragments. Some fragments contained text that
was generated immediately during the first pass of code generation;
other fragments were placeholders for parts of the program whose
generation was delayed (such as dispatch on YYFILL labels with -f option
that cannot be generated on the first pass because the full list of
labels is known only at the end of the first pass). Individual fragments
used ad-hoc methods to render the generated code, which made rendering
rather complex (for example, it was problematic to decide if the 'if'
statement should be rendered on a single line or on multiple lines).

This commit adds a new AST-like representation of the output program.
The top-level program is still a list of output blocks, but each block
is now an AST. This decouples code generation from rendering, which
simplifies both phases and allows easier customization for different
output language backends (such as C or Go).
2020-04-15 07:04:54 +01:00
Ulya Trofimovich faa5d410e5 Add tests for conditions enum with and without header file. 2020-04-13 18:12:13 +01:00
Ulya Trofimovich 9405f850a4 CMake: added comment, cosmetic formatting changes. 2020-04-11 08:39:25 +01:00
Ulya Trofimovich 9ffd690c59 Merge pull request #279 from ligfx/patch-1
CMake: only add `check` target if toplevel project
2020-04-11 01:41:56 +01:00
ligfx 907fd7dc76 CMake: only add check target if toplevel project 2020-04-10 16:18:34 -07:00
Ulya Trofimovich edab559abe Travis CI: update comment. 2020-04-09 07:42:38 +01:00
Ulya Trofimovich 702f19b2d8 Travis CI: add more cmake configurations. 2020-04-09 07:22:39 +01:00
Ulya Trofimovich d48066350d CMake: add DESTINATION to install() for compatibility with cmake-3.12.4.
Otherwise on Travis CI cmake-3.12.4 fails with errors like:

  CMake Error at CMakeLists.txt:206 (install):
    install TARGETS given no RUNTIME DESTINATION for executable target "re2c".

  CMake Error at CMakeLists.txt:356 (install):
    install TARGETS given no ARCHIVE DESTINATION for static library target
    "libre2c_static".

  CMake Error at CMakeLists.txt:365 (install):
    install TARGETS given no LIBRARY DESTINATION for shared library target
    "libre2c_shared".
2020-04-09 00:18:49 +01:00
Ulya Trofimovich 7ab95bb142 Travis CI: add experimental cmake configuration. 2020-04-09 00:04:30 +01:00
Michael Maltese b85de4e29b CMake: clean up generator expression checking for Windows 2020-04-07 21:22:40 +01:00
Michael Maltese 80cd01b587 Add CMake build scripts 2020-04-07 20:55:55 +01:00
Ulya Trofimovich 43528ddf3b CMake: add test_libre2c to make check.
Tested as:
    $ cmake -DRE2C_BUILD_LIBS=on  -B build && cd build && make check
    $ cmake -DRE2C_BUILD_LIBS=off -B build && cd build && make check
2020-04-07 00:07:24 +01:00
Ulya Trofimovich 29da9fae2b CMake: correctly set dependency on run_test.sh for testing targets.
The dependency should be relative to the build directory.

Tested as:
    $ cmake -B build && cd build
    $ make && make tests
(previously failed to build dependency run_tests.sh, now finishes
successfully).
2020-04-06 23:43:36 +01:00
Ulya Trofimovich d72d005f39 CMake: comment why static lib suffix is needed on Windows and use a generator expression. 2020-04-06 23:01:38 +01:00
Ulya Trofimovich 83f7bc8881 Merge branch 'ligfx-cmake' 2020-04-06 21:01:09 +01:00
Michael M a530570e51 Add a CMake build system
Invoke it like this on Unix:

mkdir build
cd build
cmake .. \
  [-DCMAKE_C_FLAGS=...] [-DCMAKE_CXX_FLAGS=...] \
  [-DCMAKE_EXE_LINKER_FLAGS=...] \
  [-DCMAKE_SHARED_LINKER_FLAGS=...] [-DCMAKE_STATIC_LINKER_FLAGS=...] \
  [-DCMAKE_C_COMPILER=...] [-DCMAKE_CXX_COMPILER=...] \
  [-DCMAKE_BUILD_TYPE=Debug|Release|RelWithDebInfo] \
  [-DRE2C_REBUILD_DOCS=YES] \
  [-DRE2C_BUILD_LIBS=YES [-DBUILD_SHARED_LIBS=YES|NO]] \
  [-G Ninja]
make -j # or ninja, if "-G Ninja" was used

Or on Windows, install Visual Studio's CMake tools and then open this folder.
2020-04-05 10:09:21 -07:00
Ulya Trofimovich 147fbd25e9 Do not omit labels before final non-end states when EOF rule is used.
These labels are used by the code that handles unsuccessfull YYFILL:
the lexer falls back to the final state.

This fixes bug #276 "Example 01_fill.re in docs is broken"
(reported by Angelo Haller).
2020-04-03 23:48:17 +01:00
Ulya Trofimovich 35d3ef12cd Go backend: fixed code generation for the case of EOF rule and buffer refilling.
Namely, fixed the generation of 'yyaccept' declaration and added braces
in the 'if' statement. Added a test that uses 'YYFILL' and EOF rule.
2020-03-27 22:34:03 +00:00
Ulya Trofimovich 4f24b1237b Go backend: emit correct 'yych' declaration. 2020-03-25 23:47:14 +00:00
Ulya Trofimovich f285438b6e Go backend: generate '.go' filename extension for Go tests. 2020-03-25 23:24:02 +00:00
Ulya Trofimovich 6e7f0379ff Go backend: generate correct line directives. 2020-03-25 23:02:25 +00:00
Ulya Trofimovich 61253e1969 Add a more generic option '--lang <c | go>' instead of '--golang'.
This is more extensible in case re2c needs to add a backend for some other
language. The "lang" option is now separate from the "target" option.
2020-03-25 22:37:34 +00:00
Ulya Trofimovich b7facb2192 Go support: added 'fallthrough' in goto statements. Added the first test. 2020-03-25 00:16:27 +00:00
Ulya Trofimovich 30738b9482 Initial support for Go: adding Go target and --golang option. 2020-03-24 23:37:42 +00:00
Ulya Trofimovich 8276d9b149 Revised the paper "Efficient POSIX submatch extraction on NFA".
Changes:
- added an example of TNFA
- added an example of how mark() and enum() work
- changed the explicit submatch index to a set of indices to simplify handling
  of repeated captures like ((e))
- changed benchmarks and their representation: use horizontal bar charts instead
  of linear plots
- added naming conventions and renamed the variables throughout the paper
- re-worded the abstract and introduction
- multiple small tweaks
2020-03-12 23:37:07 +00:00
Ulya Trofimovich e0b4f738f2 libre2c: Updated benchmarks. 2020-03-07 20:21:18 +00:00
Ulya Trofimovich 662b45ef46 Merge pull request #271 from samebchase/patch-1
Fix typo in README.md
2020-03-05 13:24:05 +03:00
Samuel Chase 93c59de149 Fix typo in README.md 2020-03-05 14:38:47 +05:30
Ulya Trofimovich 38f3df7721 Removed incorrect TODO comment.
The comment suggested to avoid memset of boolean array, which elements
indicate if the tag has already been updated n the current step, with
an array of integers that store step number, and thus do not require
explicit zero-initialization (step numbers are growing monotonously).

After some expreiments this idea doesn't seem so good, because:

- Update function is called multiple times for the same step value (for
  different configurations), thus requiring a more complex marker value
  that would combine step number with configuration id.

- It doesn't seem to be the bottleneck (there is another memcpy, which
  is unavoidable.
2020-02-02 12:41:35 +00:00
Ulya Trofimovich 2082759eb4 libre2c: Deduplicated conversion of tag values to submatch offsets for various algorithms. 2020-02-01 23:25:43 +00:00
Ulya Trofimovich 199c000c41 Collapse repeated captures and store the range of corresponding submatch indices.
For example, (((x))) becomes (x), where the tag for the left parenthesis has
an associated range of submatch indices [0,2,4], and the tag for the right
parenthesis has an associated range [1,3,5].
2020-02-01 21:52:53 +00:00
Ulya Trofimovich 20fdb3c36f libre2c: Store intermediate results as tags (do not convert to submatch indices). 2020-01-29 22:11:03 +00:00
Ulya Trofimovich f8f16f5af6 Output individual tag history trees for TDFA states with '--dump-dfa-tree'. 2020-01-05 11:17:54 +00:00
Ulya Trofimovich cd5c4c86e5 travis.yml: correctly expand shell variable. 2019-12-31 17:08:51 +00:00
Ulya Trofimovich bf1c67f9d7 Added forgotten debug macro stub for non-debug mode.
This fixes bug #266 "New debug macro DDUMP_DFA_TREE missing in non-debug case".
Thanks to HBBroeker for the bug report.
2019-12-31 17:01:34 +00:00
Ulya Trofimovich fbd40379e4 travis.yml: add non-debug build to the matrix. 2019-12-31 16:58:11 +00:00
Ulya Trofimovich d20cec8ca2 Merge pull request #265 from trofi/ccache-ci
.travis.yml: enable ccache to speed up incremental builds
2019-12-27 21:19:20 +00:00
Sergei Trofimovich dd4d9b2a27 .travis.yml: enable ccache to speed up incremental builds
I'm not sure what would be the actual benefit. Let's try it in action!

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2019-12-27 20:26:20 +00:00
Ulya Trofimovich 3f392d4429 Merge pull request #218 from trofi/travis-sanitizers
.travis.yml: add sanitizers into test matrix
2019-12-27 20:23:21 +00:00
Sergei Trofimovich a44ff29a24 .travis.yml: add sanitizers into test matrix
Bug: https://github.com/skvadrik/re2c/issues/215
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2019-12-27 20:14:05 +00:00
Ulya Trofimovich 01281ca563 Documented debug option '--dump-dfa-tree'. 2019-12-27 19:06:09 +00:00
Ulya Trofimovich 0a0d9eb5af Added forgotten source file to git. 2019-12-27 19:01:45 +00:00
Ulya Trofimovich 4061c451cf Added debug option '--dump-dfa-tree' that prints tag history trees. 2019-12-27 17:55:29 +00:00
Ulya Trofimovich 434b6874fb Better documentation for debug options. 2019-12-25 21:19:22 +00:00
Ulya Trofimovich 8fddc8bbcd Explicitly documented that internal options are internal and unstable. 2019-12-25 20:54:41 +00:00
Ulya Trofimovich 79c62e4e81 Added internal option '--posix-prectable <naive | complex>'.
The new option allows to specify the algorithm used to compute POSIX precedence
table. The 'complex' algorithm computes precedence table in one traversal of
tag history tree and has quadratic complexity in the number of TNFA states; it
is the default. The 'naive' algorithm has worst-case cubic complexity in the
number of TNFA states, but it is much simpler than 'complex' and may be slightly
faster in non-pathological cases.
2019-12-25 20:31:57 +00:00
Ulya Trofimovich cabebc34a0 Updated re2c version in the manpage. 2019-12-14 11:50:42 +00:00
Ulya Trofimovich e1901b71c6 Release 1.3. 2019-12-14 11:43:05 +00:00
Ulya Trofimovich ca41c365a8 Updated CHANGELOG. 2019-12-13 23:36:16 +00:00
Ulya Trofimovich a55c2bc888 Fixed -Wmissing-prototypes warning. 2019-12-12 07:37:27 +00:00
Ulya Trofimovich fcce896f45 Fixed -Wshadow warning. 2019-12-12 07:29:49 +00:00
Ulya Trofimovich 8f505bf35a Fixed -Wformat warnings on systems with 32-bit size_t. 2019-12-12 07:08:55 +00:00
Ulya Trofimovich fdc4f0b20b Added a fuzz-testing script that checks staDFA vs TDFA. 2019-12-11 23:13:28 +00:00
Ulya Trofimovich a1d38915dc Added staDFA to libre2c (library, test and benchmark).
Note: some REs in the benchmark have too many tag variables with staDFA,
but not with TDFA.
2019-12-11 22:55:55 +00:00
Ulya Trofimovich e2bb60616d Added a few more (non-POSIX) tests for staDFA. 2019-12-11 07:18:40 +00:00
Ulya Trofimovich 51a26ff4b2 Added POSIX tests for staDFA. 2019-12-11 07:16:43 +00:00
Ulya Trofimovich 53d4239f38 Added staDFA to POSIX testing script. 2019-12-11 00:00:58 +00:00
Ulya Trofimovich d729b5f105 Added skeleton support for staDFA. 2019-12-10 23:56:30 +00:00
Ulya Trofimovich d0089f9c46 Implemented staDFA algorithm.
The algorithm is described in the paper "STADFA: An efficient Subexpression
Matching Method" by Mohammad Imran Chowdhury.

The main difference between staDFA and TDFA is in the placement of tag actions:
staDFA places them in states, while TDFA places them on transitions. RE2C
implementation of staDFA differs from the description in the paper in a number
of aspects:

- We use TNFA with epsilon-transitions instead of Glushkov automaton used by
  Chowdhury. Glushkov automaton is not ambiguity-preserving, unless it is
  modified to have multi-transitions between a pair of states, which differ
  only in the tag sequences assigned to them. Such multi-transitions are used
  by the original Okui-Suzuki PAT, but there is a problem with this idea: the
  number of multi-transitions may grow exponentially with the size of RE.

- We use the same disambiguation algorithms as those used for TDFA, not those
  described by Chowdhury.

- We associate tag indices with TNFA states, and not symbols occurrences in RE.
  In principle this is the same: for each occurrence of a given symbol there is
  a distinct TNFA state (the same state corresponds to multiple symbols from
  the same range, but not for multiple occurrences of the same symbol).

- We always use "delayed store" actions, as we need to know the values of tags
  under repetition either on the last iteration (for s-tags), or on all
  iterations (for m-tags).

- We compare lookahead tags when looking for an identical state.

- We compare POSIX precedence matrces when looking for an identical state.

- We use negative tags.

- We don't add "delayed store" actions for lookahead tags of the origin state
  which do not have current transiiton symbol in their lookahead set.

- We create initial transfer actions for all tags and all sub-states of the
  initial state. This ensures that there is an action for every final sub-state.

- We resolve cycles in tag commands using temporary variables.
2019-12-10 22:54:53 +00:00
Ulya Trofimovich 749be69c87 Updated docs for YYSTAGPD and YYMTAGPD configurations. 2019-12-10 07:28:09 +00:00
Ulya Trofimovich 110759bd44 Added configurations YYSTAGPD and YYMTAGPD for staDFA "delayed store" actions. 2019-12-10 07:25:50 +00:00
Ulya Trofimovich 79507076d7 Updated docs for --stadfa option. 2019-12-10 07:23:47 +00:00
Ulya Trofimovich 7d0efb24ba Added option --stadfa. 2019-12-10 07:18:36 +00:00
Ulya Trofimovich 4b78bb9970 Fixed formatting (cosmetic). 2019-12-09 23:45:14 +00:00
Ulya Trofimovich 1ab39d457d Use size_t instead of int32_t to avoid overflow in array index on REs with many tags.
Interference table is square in the number of tag variables, so 32-bit signed
indices into it overflow when the number of tag variables approaches 2^16.
With this fix overflow may still happen on platforms that have 32-bit size_t,
or on REs with too many tags.
2019-12-09 23:12:57 +00:00
Ulya Trofimovich b96092ab54 Consistently remove duplicates when optimizing in tag commands.
Duplicate commands may arise as a result of tag optimizations, and should be
removed in all cases ("set', "copy" and "add" commands). In case of "set"
commands this can be done by sorting commands and removing adjacent duplicates.
In case of "add" commands sorting is not possible, but deduplication can still
be implemented using naive quadratic algorithm. Deduplication of "copy" commands
depends on the presence of cycles (if there are no cycles, it is possible to
sort commands lexicographically, then remove adjecent duplicates, then sort
commands topologically).
2019-12-09 22:58:07 +00:00
Ulya Trofimovich 4e63b087cc Reworked topsort of tag commands to accept end pointer and return the first non-trivial cycle.
Accepting end pointer rather than assuming NULL-terminated list of commands is
convenient when the topsorted list is a sublist in the middle of a larger list.

Returning a pointer to the first non-trivial cycle is needed in ordert to break
the cycle by introducing a temporary variable; this is needed for implementing
staDFA.
2019-12-09 07:43:26 +00:00
Ulya Trofimovich 2adb40ea81 Handle block-local liveness in dead code elimination.
This is needed in preparation for staDFA implementation. Variables local to
basic block may occur as a result of breaking cycles in a sequence of tag
commands by introducing temporary variables. TDFA mappings have no cycles
(such mappings are rejected), but staDFA transfer actions often do, because
the indices used in the actions are bound to TNFA substates, which may be
flipped in the origin and target staDFA states.
2019-12-08 23:57:36 +00:00
Ulya Trofimovich 1322bc25d5 Don't use 'Mrecord' Graphviz shape for '--dump-dfa-raw' output as it doesn't work correctly with HTML labels. 2019-12-08 23:36:16 +00:00
Ulya Trofimovich 8d713fbe39 Skeleton: abort if history length exceeds maximum value of key type.
Ideally we should use different encoding (e.g. always allow 2 or 4 bytes
for history length), but that requires more complex serialization and
deserialization. Assert is a temporary measure.
2019-12-08 23:19:09 +00:00
Ulya Trofimovich 01ad5dccfd Skeleton: make m-tag pool relocatable by using indices instead of pointers.
M-tag pool is reallocated and moved when it runs out of space. However,
previously it contained an array of structs with pointers to elements of this
array. After moving these pointers where no longer valid.
2019-12-08 23:19:09 +00:00
Ulya Trofimovich 36a5f79f40 Don't allocate unused tag variable.
In some cases this was causing increase in the number of tag variables after
optimizations, which is generally bad and also caused memory access violation
as the liveness/interference tables are allocated for the initial number.

The 0-th variable is superficial and does not correspond to a real tag version
(zero is a special version reserved for "no tag operation"). In the variable
allocation algorithm it is convenient to handle zero in the same way as other
variables (because arrays are indexed from zero). In most of the cases 0-th
variable ends up in a class that contains other (non-fake) variables, but if it
is alone in its class, then no tag variable should be allocated for this class.
2019-12-08 23:19:09 +00:00
Ulya Trofimovich 0686c48bfc Don't ignore interference induced by fallback tag commands. 2019-12-08 23:19:08 +00:00
Ulya Trofimovich 1e1a376c05 Reworked CFG construction to allow tags both in states and on transitions.
This is needed in preparation for implementing staDFA algorithm, in which
tag operations are placed in states, not on transitions. The new CFG model
is able to accommodate both TDFA and staDFA, as well as a hypothetical
"mixed" case where tag operations occur both in states and on transitions.

This commit adds "canonical" marking of visited states and transitions, which
allows to avoid erroneous creation of dulicate arcs in the CFG.

Some of the helper functions have been rewritten from recursion to iteration.

This commit also adds CFG construction context to avoid passing too many
parameters to the helper functions.
2019-12-08 23:19:08 +00:00
Ulya Trofimovich 9ac4408a55 Use correct index for the final substate in the .dot output for '--dump-dfa-raw'. 2019-12-08 23:19:01 +00:00
Ulya Trofimovich 4477437525 Prioritize normal rule that matches empty string over EOF rule. 2019-12-08 19:19:43 +00:00
Ulya Trofimovich 4b006d7f00 Do not remove shadowed rules if EOF rule is used.
With EOF rule, it is always possible that EOF happens before the next matching
rule, even if it matches all possible inputs. If EOF does happen, the lexer
needs to rollback to the last matched rule (so it is not dead).
2019-12-08 19:16:39 +00:00
Ulya Trofimovich 45f561e3b2 Moved code that decides on tag hoisting to a separate function with a comment. 2019-12-08 19:13:16 +00:00
Ulya Trofimovich 08508a6342 Changed the decsription of tags in docs to avoid ambiguity.
Thanks to Des-Nerger for pointing out in bug #140.
2019-10-11 07:42:50 +01:00
Ulya Trofimovich 2ee9c50c05 Added ninja lexers to tests.
Note: ninja_lexer.ib.c differs from the original lexer in the ninja project,
because the latter was generated with re2c-0.16, which used slightly
different constructs for complex expressions:

Re2c-0.16 used generated something like this:

    ++YYCURSOR;
    if (yych = *YYCURSOR) ...

And the latest re2c generates something like this:

    yych = *++YYCYRSOR;
    if (yych) ...

The difference is insignificant.
2019-09-01 10:03:48 +01:00
Ulya Trofimovich 94faf98935 Moved tests into subdirectories and deleted some of the largest skeleton tests. 2019-09-01 10:01:44 +01:00
Ulya Trofimovich e34fe4dde7 libre2c: added prefix 'TOKEN_' to all parser tokens to avoid name collisions.
Apparently some versions of bison generate token definitions as macros, not
as enum members. If a bison-generated header is included into another file
that contains identifiers identical to the names of parser tokens, all such
identifiers are macro-substituted to a numeric constant. Adding a prefix to
token names reduces the chances of name collision.

This fixes bug #261: "lib/parse.h:49:15: 错误:expected unqualified-id before
numeric constant" reported by qidizi.
2019-08-29 22:27:01 +01:00
Ulya Trofimovich 269578f8d4 Fixed documentation regarding '...:naked' configurations. 2019-08-28 23:42:01 +01:00
Ulya Trofimovich 257b318439 Respect 're2c:define:YYFILL:naked' and 're2c:yyfill:parameter' configurations with EOF rule.
Thanks to Nazim Can Bedir for the bug report.
2019-08-28 23:10:10 +01:00
Ulya Trofimovich 47f7742d2e Updated documentation for the new 're2c:sentinel' configuration. 2019-08-25 11:17:16 +01:00
Ulya Trofimovich 82d1833970 Added some tests for 're2c:sentinel' configuration. 2019-08-25 10:41:58 +01:00
Ulya Trofimovich de63b8baed Added -Wsentinel-in-midrule warning and 're2c:sentinel' configurations.
The new analysis is meant to detect potential reads past the end of buffer
resulting from erroneous rules that allow sentinel symbol to occur in the
middle of lexeme. The analysis is only activated in cases bounds checking
is disabled with 're2c:yyfill:enable = 0;' and EOF rule is not used.

For example:

    ['] [^']* [']   { ... }

This may be a naive way to match single-quoted strings; it would crash the
lexer on input like "'aaa\0" (without the closing single quote).
2019-08-25 10:22:09 +01:00
Ulya Trofimovich 7648f8dd9e Got rid of PACKAGE_DATE variable altogether (it was used only in the manpage). 2019-08-17 21:39:04 +01:00
Ulya Trofimovich 7e10b11a0a Merge pull request #258 from lamby/934697-re2c-please-make-the-build-reproducible
Make the build reproducible
2019-08-14 07:18:18 +01:00
Chris Lamb a4c0ff1bf8 Make the build reproducible
Whilst working on the Reproducible Builds effort [0] we noticed
that re2c could not be built reproducibly.

This is because it used the current build date in the manual page and was
originally filed in Debian as #934697 [1].

This patch uses the SOURCE_DATE_EPOCH [2] environment variable.

 [0] https://reproducible-builds.org/
 [1] https://bugs.debian.org/934697
 [2] https://reproducible-builds.org/specs/source-date-epoch/

Signed-off-by: Chris Lamb <lamby@debian.org>
2019-08-13 13:53:04 -07:00
Ulya Trofimovich f2df7574a9 Merge pull request #256 from certik/license
Package LICENSE file in the release tarball
2019-08-13 06:54:05 +01:00
Ulya Trofimovich 8449d452d1 Updated bootstrap manpage. 2019-08-13 06:49:26 +01:00
Ulya Trofimovich 78ea5562ba Merge pull request #255 from jcfp/master
fix documentation typos
2019-08-13 06:47:32 +01:00
Ondřej Čertík a933242be9 Package LICENSE file in the release tarball
This is important when re2c is packaged in distributions, so that one can
quickly check what license the re2c is distributed under. Distributions
typically use the release tarball, not the git repository, and so this commit
puts the LICENSE file into the release tarball also.
2019-08-12 22:26:40 -06:00
jcfp f5072bf4ce fix documentation typos 2019-08-12 12:41:10 +02:00
Ulya Trofimovich b644493b05 Release 1.2.1. 2019-08-11 09:38:33 +01:00
Ulya Trofimovich 3a24a0cc07 Updated CHANGELOG. 2019-08-11 09:23:17 +01:00
Ulya Trofimovich c3880fc84e Install standard library files in $(datadir)/re2c/stdlib and search for include files in this location.
This fixes bug #253 "re2c should install unicode_categories.re somewhere"
(reported by Wesley W. Terpstra).
2019-08-07 23:19:21 +01:00
Ulya Trofimovich 27156203d3 Allow to reset 're2c:eof' configuration.
The ability to reset this configuration is necessary in order to be able to
mix re2c blocks that use EOF rule and blocks that don't.

This fixes bug #254: "Turn off re2c:eof".
2019-08-05 23:33:10 +01:00
Ulya Trofimovich f5af0a118a Release 1.2. 2019-08-02 12:36:08 +01:00
Ulya Trofimovich c8a30e4103 Updated release script. 2019-08-02 12:35:55 +01:00
Ulya Trofimovich 259c07e0ba Added include/ subdirectory to distribution and updated bootsrap files. 2019-08-02 10:51:06 +01:00
Ulya Trofimovich 86fd545415 Fixed release date in CHANGELOG. 2019-08-02 10:26:46 +01:00
Ulya Trofimovich 8948d1a318 Re-applied manpage updates (accidentally reverted by previous commits). 2019-08-01 23:47:00 +01:00
Ulya Trofimovich b16164af2a Updated CHANGELOG (converted to RST format to be in sync with gh-pages-gen branch). 2019-08-01 13:52:01 +01:00
Ulya Trofimovich f04d430876 Updated manpage. 2019-07-29 16:01:09 +01:00
Ulya Trofimovich 0ff847aa8c Regenerated bootstrap files (some files were not updated after include-what-you-use fixes). 2019-07-26 11:33:28 +01:00
Ulya Trofimovich b093c9f86b Paper: cleaned up source files (mostly removed unused files).
Touched the following papers:
- 1994 paper "RE2C: a More Versatile Parser Generator"
- 2017 paper "Tagged Deterministic Finite Automata with Lookahead" (after arXiv publication)
- 2019 paper "Efficient POSIX Submatch Extraction on NFA"

All .pdf and .ps files have been moved to gh-pages-gen branch.
2019-07-26 11:31:59 +01:00
Ulya Trofimovich 40951cd1c2 Fixed code generation for EOF rule with '-f --storable-state' option. 2019-07-25 09:21:20 +01:00
Ulya Trofimovich 5ad271b8ff Paper: added acknowledgements and adjusted formatting. 2019-07-24 10:45:06 +01:00
Ulya Trofimovich 640d6c93c5 Paper: use pgfplots instead of gnuplot to render benchmark results. 2019-07-23 17:10:55 +01:00
Ulya Trofimovich 5da0871c2e Paper: taken care of Angelo's remarks (mostly grammar fixes). 2019-07-23 12:11:58 +01:00
Ulya Trofimovich 34b7df3ae8 Don't generate 'YYFILL' calls when EOF rule is used with 're2c:yyfill:enable = 0;' configuration.
Note: in the non-EOF-rule case 're2c:yyfill:enable = 0;' results in suppression
of the whole 'YYLIMIT' check together with 'YYFILL' call. In case of EOF rule,
however, we are not bound by backward compatibility and can do a more logical
thing.
2019-07-18 17:26:27 +01:00
Ulya Trofimovich 7ecd5e8e1a Fixed the case of missing default label which is used only by EOF checks.
The current fix may sometimes cause generation of unused default label, because
at the time when it's generated we haven't geerated the code for EOF checks yet
and do nt know if default label is really needed. This is what happens in the
updated test cases.
2019-07-18 17:16:04 +01:00
Ulya Trofimovich 8090e4349e Omit unnecessary 'else' when generating code for EOF checks. 2019-07-18 17:04:05 +01:00
Ulya Trofimovich 842864de68 Renamed misleadingly named parameter. 2019-07-18 16:56:47 +01:00
Ulya Trofimovich e3939e8ffd Updated CHANGELOG. 2019-07-17 23:43:25 +01:00
Ulya Trofimovich 1e09560e0e Updated documentation for new options and directives. 2019-07-17 23:40:51 +01:00
Ulya Trofimovich 9432cc5df0 Moved include file with definitions of Unicode categories to 'include/' subdirectory. 2019-07-15 15:56:29 +01:00
Ulya Trofimovich 943aee82e3 Use cast to 'void' instead of attribute 'unused', otherwise we get -Wused-but-marked-unused in debug mode. 2019-07-14 00:02:35 +01:00
Ulya Trofimovich 57554ba6bb Added a few casts to 'printf' args to silence warnings caused by different type width in 32/64 modes. 2019-07-13 23:46:11 +01:00
Ulya Trofimovich 00727c3ce9 libre2c test: always run Cox algorithm and skip expected failures. 2019-07-13 23:46:00 +01:00
Ulya Trofimovich b50f1bc3c4 Cosmetic: shortened macro name a bit and removed 'GXX' as it is also relevant to Clang. 2019-07-13 19:09:00 +01:00
Ulya Trofimovich 5733b55e18 Marked a few debug variables as unused to avoid warnings in release builds. 2019-07-13 19:00:12 +01:00
Ulya Trofimovich ba793956ad Makefile.am: added forgotten 'AM_V_GEN' prefix to a couple of build rules. 2019-07-13 18:45:48 +01:00
Ulya Trofimovich a89e9ec3dc Disable ceratain warnings on bison-generated output (we have no control over it). 2019-07-13 18:36:03 +01:00
Ulya Trofimovich 51b5fe7be0 Fixed Clang warning -Wshift-sign-overflow. 2019-07-13 11:42:37 +01:00
Ulya Trofimovich b584467153 Fixed Clang warning -Wexit-time-destructors. 2019-07-13 11:39:52 +01:00
Ulya Trofimovich 71638e1fad Fixed Clang warning -Wconditional-uninitialized. 2019-07-13 11:37:11 +01:00
Ulya Trofimovich 27ad1deb15 Fixed Clang warning -Wmissing-variable-declarations. 2019-07-13 11:34:34 +01:00
Ulya Trofimovich d7ad1cd6e6 Fixed Clang warning -Wunused-template. 2019-07-13 11:32:04 +01:00
Ulya Trofimovich 273532a26b Fixed Clang warning -Wunreachable-code (these were real serious errors). 2019-07-13 11:25:25 +01:00
Ulya Trofimovich 069be61f3d Fixed Clang warning -Wunreachable-code-return. 2019-07-13 11:23:29 +01:00
Ulya Trofimovich 0f9b22f86f Fixed Clang warning -Wmissing-prototypes. 2019-07-13 11:20:38 +01:00
Ulya Trofimovich 388cde74be Fixed Clang warning -Wc++11-extensions. 2019-07-13 11:16:21 +01:00
Ulya Trofimovich c91defab6f Fixed Clang warning -Wmismatched-tags. 2019-07-13 11:13:18 +01:00
Ulya Trofimovich cb5fee0667 Fixed Clang warnings -Wswitch-enum and -Wcovered-switch-default. 2019-07-13 11:09:39 +01:00
Ulya Trofimovich 5bb8aa5281 Fixed Clang warning -Wshadow. 2019-07-13 11:03:13 +01:00
Ulya Trofimovich f979535960 Fixed Clang warnings -Wextra-semi and -Wextra-semi-stmt. 2019-07-13 10:49:09 +01:00
Ulya Trofimovich acf9d2257f configure.ac: silenced a few Clang warnings (too noisy, not very helpful). 2019-07-13 10:37:36 +01:00
Ulya Trofimovich 7b9dee1908 Fixed test (added forgotten qualification after moving functions into 're2c' namespace). 2019-07-12 14:57:38 +01:00
Ulya Trofimovich 50a0a137a8 Added build script that checks that all headers are self-contained. 2019-07-12 14:31:02 +01:00
Ulya Trofimovich 3e0e62ced8 Fixed includes using include-what-you-use. 2019-07-12 13:35:40 +01:00
Ulya Trofimovich 0755d98b32 Added build script for include-what-you-use. 2019-07-12 11:40:43 +01:00
Ulya Trofimovich fcfcef0592 Updated Mingw build scripts to workaround libtool/slibtool issues.
Currently we need both libtool and slibtool:

  - libtool fails to link self-contained DLL (it ignores '-static-libstdc++
    -static-libgcc'), but manages to link EXEs with static library

  - slibtool manages to link self-contained DLL, but then fails to link the
    final EXEs with it (it passes '-lre2c' before some other predefined object
    file that contains definitions from libgcc)
2019-07-11 19:12:04 +01:00
Ulya Trofimovich 7bbd3047af run_tests.sh: check for re2c existence after (possibly) appending .exe extension. 2019-07-11 12:28:44 +01:00
Ulya Trofimovich 987171e39d Build scripts: changed -j5 to -j$(nproc). 2019-07-11 11:34:59 +01:00
Ulya Trofimovich b3c0e3c5aa Paper: fixed broken references. 2019-07-10 19:03:19 +01:00
Ulya Trofimovich 4d7d314111 Paper: references and spell-checking. 2019-07-10 11:33:04 +01:00
Ulya Trofimovich 597e67d779 Paper: updated and fixed all the proofs. 2019-07-08 11:55:34 +01:00
Ulya Trofimovich 8cd026cde2 Paper: reworked "Benchmarks" section, added "Conclusions and future work" section. 2019-06-26 12:38:28 +01:00
Ulya Trofimovich 0d5342dd97 libre2c: don't forget to free static lists (AST nodes, etc.) at the end of 'regfree()'.
Otherwise they accumulate at every 'regcomp()'.
2019-06-26 11:18:26 +01:00
Ulya Trofimovich 6af3eac676 libre2c: clean up cache after matching in lazy algorithms; small tweaks in benchmark.
Cleaning up cache may take considerable time (e.g. if cache is a large
std::map), which should be included in the match time.
2019-06-26 11:17:49 +01:00
Ulya Trofimovich 8f6a38d37f Added 'clear()' method to slab allocator. 2019-06-25 22:57:24 +01:00
Ulya Trofimovich ce812b6922 Paper: removed nested negative tags from TNFA and added complexity analysis. 2019-06-22 22:27:15 +01:00
Ulya Trofimovich 96e5cfbe91 libre2c: don't add nested negative tags to TNFA, as it increases its size and makes matching slower.
Instead, add only one negative tag (top-level closing one) and record
the remaining tags in its metadata. Use this metadata to update nested
negative tags during TNFA simulation.
2019-06-21 14:51:26 +01:00
Ulya Trofimovich bd705ce24e libre2c benchmark: make a couple of warmup iterations before the main run. 2019-06-17 20:49:31 +01:00
Ulya Trofimovich 195158404b Paper: added "Benchmarks" section. 2019-06-17 20:49:25 +01:00
Ulya Trofimovich 8f5bf0b2ec libre2c benchmark: print size of each regular expression and the number of capturing groups in it. 2019-06-17 10:27:07 +01:00
Ulya Trofimovich e2c856acc4 libre2c: removed unused variable. 2019-06-13 16:49:02 +01:00
Ulya Trofimovich de86635c9d Makefile.am: added 'bench_libre2c' to noinst_PROGRAMS (so that automake picks it as a target). 2019-06-13 16:43:36 +01:00
Ulya Trofimovich 9a0332bd41 Paper: added section about lazy disambiguation. 2019-06-12 23:45:46 +01:00
Ulya Trofimovich a00dc48711 Added a test for '--input-encoding utf8' option. 2019-05-24 15:12:28 +01:00
Ulya Trofimovich 29a6d01984 Added option --input-encoding <ascii | utf8> that allows to use UTF-8 literals in regular expressions. 2019-05-24 13:15:07 +01:00
Ulya Trofimovich 55d9c87a54 Allow to mix multiple /*!rules:re2c*/, /*!use:re2c*/ and /*!re2c*/ blocks in -r mode. 2019-05-24 12:04:47 +01:00
Ulya Trofimovich 71c195e40b libre2c: added GOR1 option for lazy disambiguation algorithm. 2019-05-18 19:20:17 +01:00
Ulya Trofimovich cc1f26bc81 libre2c: do not include benchmark in 'make check' programs. 2019-05-09 22:38:12 +01:00
Ulya Trofimovich 9222dd03fb libre2c: added forgotten benchmark data samples. 2019-05-09 21:45:06 +01:00
Ulya Trofimovich ef25066072 libre2c: added missing include. 2019-05-09 21:29:53 +01:00
Ulya Trofimovich fd0195dd4b libre2c: updated benchmark. 2019-05-09 18:30:32 +01:00
Ulya Trofimovich ea2b021571 libre2c: extended lexer to handle some escape sequences in charachter classes. 2019-05-08 14:31:14 +01:00
Ulya Trofimovich 4f0c2bce30 Inlined closure cleanup in the pruning procedure to further speedup determinization. 2019-05-08 11:01:48 +01:00
Ulya Trofimovich 93d7b98f2c Make unreachable rule analysis conditional to further sppedup closure pruning. 2019-05-08 10:54:00 +01:00
Ulya Trofimovich 5b6215faff Rewrite of closure pruning function to speedup determinization on large automata. 2019-05-08 10:44:25 +01:00
Ulya Trofimovich 22b975cba7 Hash in 4-byte chunks to speedup determinization on large automata. 2019-05-08 09:57:59 +01:00
Ulya Trofimovich cf24d925dc Use correct formula to find the next aligned address.
The previous formula worked incorrectly for already aligned addresses
(it added alignment to them).
2019-05-08 07:35:42 +01:00
Ulya Trofimovich 9b640359e9 Paper: updated "TNFA construction" section. 2019-04-09 22:50:26 +01:00
Ulya Trofimovich c32d433a97 configure.ac: use AC_USE_SYSTEM_EXTENSIONS, as --std=c++98 disables POSIX extensions on Cygwin.
Attempted fix for #247.
2019-04-06 11:16:47 +01:00
Ulya Trofimovich b3cd7b677c Makefile.am: reflected the rename of README to README.md.
This fixes bug #248.
2019-04-06 10:33:20 +01:00
Ulya Trofimovich fbfcf09058 Paper: updated sections about representation of paths and match results. 2019-04-05 17:21:30 +01:00
Ulya Trofimovich c0b022cb8b Paper: rearranged "epsilon-closure" section. 2019-04-05 10:34:03 +01:00
Ulya Trofimovich 08f57a4dc5 Paper: updated pseudocode for precedence procedures. 2019-04-02 13:48:52 +01:00
Ulya Trofimovich 08703630a8 Paper: restructured "formalization" section. 2019-04-01 22:57:12 +01:00
Ulya Trofimovich d068a4add0 Paper: wrote "main idea" section. 2019-04-01 14:48:48 +01:00
Ulya Trofimovich 8d7946a18f libre2c: restructured main loop to avoid double call to closure. 2019-03-30 09:59:50 +00:00
Ulya Trofimovich 6539d67b8f Paper: wrote the "introduction" section. 2019-03-29 14:40:59 +00:00
Ulya Trofimovich d135ee8439 Fixed compilation error caused by extra namespace qualification (second attempt). 2019-03-26 18:22:42 +00:00
Ulya Trofimovich d01587ec63 Fixed compilation error caused by extra namespace qualification. 2019-03-26 18:18:34 +00:00
Ulya Trofimovich 1edbf39bc0 libre2c: implemented Kuklewicz disambiguation algorithm for POSIX TNFA matching. 2019-03-26 17:56:51 +00:00
Ulya Trofimovich fbcb1ef0b0 libre2c: free tag history after each step (it's no longer needed).
Seems to be a copy-paste error from TDFA implementation, where history
for each state is needed until the end of determinization.
2019-03-25 16:40:04 +00:00
Ulya Trofimovich 42ddca5a02 Parameterize determinization/simulation context directly by history type. 2019-03-25 14:32:39 +00:00
Ulya Trofimovich 4d65fa8cb6 Added logs with test failures of backward matching algorithm. 2019-03-25 07:26:43 +00:00
Ulya Trofimovich a6cde61812 libre2c: added Cox backward matching algorithm (incorrect, but interesting). 2019-03-24 10:27:42 +00:00
Ulya Trofimovich c1fcecefa4 Fictive tags for right alt/cat must be added after adding all tags for left alt/cat.
Previous order was incorrect: fictive tags for both left and right
alternative or catenation were added before recursing into the right
alternative or catenation. This resulted in right fictive tags habving
higher precedence than left non-fictive tags.
2019-03-24 09:31:56 +00:00
Ulya Trofimovich 8d8f1767b6 Debug: don't print NFA in-degree in each node, it takes too much space. 2019-03-24 09:28:59 +00:00
Ulya Trofimovich b0c0edd501 libre2c: added POSIX tests that show why closure can't use DFS and needs worst-case quadratic shortest path algorithm.
In particular, test ((((a?)+)|(aa))+) and string "aaa" demonstrates why
we cannot replace SSSP (GOR1 or GTOP) with a liner-time DFS that sets
predecessor chains of TNFA states and sorts initial closure configurations
according to POSIX relation imposed by precedence matrix.

Consider what happens after consuming the first to 'a's (see the .dot
encoded TNFA below):

- initial states are 8, 14 and 9 (in the order imposed by D-matrix)

- start DFS from 8

- find path 8->7->6->5->4->3->2->22->21->11->10

- find path 8->7->6->5->4->3->2->22->21->20->19->18->17->16->15

- find path
  8->7->6->5->4->3->2->22->21->20->19->18->17->16->14->13->17
  compare it to the previous path to 17 and discard the new looping path

- find path
  8->7->6->5->4->3->2->22->21->20->19->18->17->16->14->13->12->3
  compare it to the previous path to 3 and discard the new looping path

- find path 8->7->6->5->4->3->2->1->0

- DFS from 8 complete, start DFS from 14

- find path 14, compare it to the previous path to 14 and accept the new
  one as it is better (but do not attempt to propagate the improvement
  and rescan states: this is DFS, not GOR1, and the whole idea is to
  avoid rescanning and have linear complexity)

- DFS from 14 complete, start DFS from 9

- find path 9

The end, and we have an incorrect path to 15: the long path through the
outer loop from 8, rather than the short path through the inner loop
from 14. This further leads to incorrect results.

digraph NFA {
  rankdir=LR
  node[shape=Mrecord fontname=Courier height=0.2 width=0.2]
  edge[arrowhead=vee fontname=Courier label=" "]

  n23 [label="23"]
  n23 -> n22 [label="/0&uarr;(1)"]
  n22 [label="22"]
  n22 -> n21 [label="/2&uarr;(2)"]
  n21 [label="21"]
  n21 -> n11
  n21 -> n20 [color=lightgray]
  n20 [label="20"]
  n20 -> n19 [label="/4&darr;(3)"]
  n19 [label="19"]
  n19 -> n18 [label="/5&darr;(2)"]
  n18 [label="18"]
  n18 -> n17 [label="/6&uarr;(3)"]
  n17 [label="17"]
  n17 -> n16 [label="/8&uarr;(4)"]
  n16 [label="16"]
  n16 -> n15
  n16 -> n14 [color=lightgray]
  n15 [label="15"]
  n15 -> n14 [label="97"]
  n14 [label="14"]
  n14 -> n13 [label="/9&uarr;(3)"]
  n13 [label="13"]
  n13 -> n17
  n13 -> n12 [color=lightgray]
  n12 [label="12"]
  n12 -> n3 [label="/7&uarr;(2)"]
  n11 [label="11"]
  n11 -> n10 [label="/4&uarr;(3)"]
  n10 [label="10"]
  n10 -> n9 [label="97"]
  n9 [label="9"]
  n9 -> n8 [label="97"]
  n8 [label="8"]
  n8 -> n7 [label="/5&uarr;(2)"]
  n7 [label="7"]
  n7 -> n6 [label="/6&darr;(3)"]
  n6 [label="6"]
  n6 -> n5 [label="/8&darr;(4)"]
  n5 [label="5"]
  n5 -> n4 [label="/9&darr;(3)"]
  n4 [label="4"]
  n4 -> n3 [label="/7&darr;(2)"]
  n3 [label="3"]
  n3 -> n2 [label="/3&uarr;(1)"]
  n2 [label="2"]
  n2 -> n22
  n2 -> n1 [color=lightgray]
  n1 [label="1"]
  n1 -> n0 [label="/1&uarr;(0)"]
  n0 [label="0"] [fillcolor=gray]
}
2019-03-16 23:52:33 +00:00
Ulya Trofimovich f8aad4ebd0 Use state index in closure instead of core index, and don't keep core indices at all. 2019-03-08 07:21:49 +00:00
Ulya Trofimovich 2d32276383 Added tests for errors in case of out-of-bounds EOF value. 2019-03-07 23:09:02 +00:00
Ulya Trofimovich c7ffeff9ab Give a concise error message when EOF rule is present, but no other rules are. 2019-03-07 22:51:11 +00:00
Ulya Trofimovich d5fb50e958 Updated .gitignore. 2019-03-07 22:09:05 +00:00
Ulya Trofimovich 03e3d4ed59 Updating .travis.yml after global move. 2019-03-07 18:47:04 +00:00
Ulya Trofimovich f38473365c Moved re2c subdirectory to root directory and renamed old libre2c to libre2c_old. 2019-03-07 18:28:49 +00:00
Ulya Trofimovich 4fda031a2f Makefile.am: use wildcard instead of braces in macro expansion (the latter breaks on BSD). 2019-03-07 17:21:34 +00:00
Ulya Trofimovich af7f6db989 Avoid using ULLONG_MAX as it is non-standard prior to C++11. 2019-03-07 16:24:16 +00:00
Ulya Trofimovich a804c1e35f Handle cases when rename() fails because destination file exists.
In C/C++ rename() behaviour is implementation-defined. POSIX and Windows
have different behaviour when destination file exists: POSIX says rename()
should overwrite it, but Windows says rename() should fail.
2019-03-07 13:08:51 +00:00
Ulya Trofimovich 47e1c662d1 Added more tests for EOF rule. 2019-03-06 23:28:29 +00:00
Ulya Trofimovich 3e1299fc49 Improved label generation with EOF rule (removed unused and added missing labels). 2019-03-06 21:47:49 +00:00
Ulya Trofimovich b9d9c92dcf Added some tests for EOF rule. 2019-03-06 16:06:39 +00:00
Ulya Trofimovich 370d92913a Fixed EOF rule handling in case when EOF symbol is the upper bound of charset. 2019-03-06 14:54:00 +00:00
Ulya Trofimovich 5fd969a717 run_tests.sh: ignore difference in trailing whitespace with --wine option. 2019-03-06 12:15:48 +00:00
Ulya Trofimovich f701e44e0e Added test for newline conversion. 2019-03-06 12:05:25 +00:00
Ulya Trofimovich 18b47c0af9 Consistently convert all newlines in the generated file to Unix-style LF.
Some newlines originate in user-defined code (including semantic actions
and code fragments in configurations and directives), some are generated
by re2c itself. In order to maintain consistency we convert all newlines
to LF when writing output to file.
2019-03-06 12:00:23 +00:00
Ulya Trofimovich ba30090e89 Need to include <fcntl.h> with MSVC to get definitions of _O_CREAT, _O_EXCL and _O_RDWR. 2019-03-06 08:43:53 +00:00
Ulya Trofimovich 3c1219ce1a Avoid warnings about uninitialized variables. 2019-03-06 07:12:06 +00:00
Ulya Trofimovich 91ff856c6b Use macro _MSC_VER instead of nonexistent _MSVC to detect Visual Studio. 2019-03-06 07:07:51 +00:00
Ulya Trofimovich 0665c39c36 Do not access vector element by reference that is invalidated due to reallocation. 2019-03-05 22:44:21 +00:00
Ulya Trofimovich 2e7bcb3205 Use autoconf header detection to guard non-C++98 includes (POSIX file API). 2019-03-05 22:09:08 +00:00
Ulya Trofimovich 7e51fb5b0e Use something that Mingw understands instead of UINTMAX_MAX from <stdint.h>. 2019-03-05 17:55:37 +00:00
Ulya Trofimovich 2d30bc1566 Write output to temporary file and then rename it to output file atomically.
This is more conveniet for build systems: if code generation is interrupted
for some reason, we don't end up with half-generated or empty output file.

Note that re2c there still can be discrepancy between the generated header
file and output file.
2019-03-05 17:48:46 +00:00
Ulya Trofimovich bb6b18c8a8 Use C array instead of vector (of known size) to avoid iterator invalidation warnings. 2019-03-05 15:50:51 +00:00
Ulya Trofimovich 40b7de0f02 Respect platforms with 32-bit 'long' and 64-bit pointers.
Previously used ~0U works incorrectly in such cases: ~0U equals
0xFFFFffff, and maximum (numerical) pointer value is 0xFFFFffffFFFFffff.
This caused incorrect comparison result when tracking include files that
have been fully processed and can be removed frm the include stack.

Problem report thanks to Denis Naumov.
2019-03-05 10:50:00 +00:00
Ulya Trofimovich 6be70b2586 Renamed README to README.md to make github render it nicely. 2019-03-04 17:54:23 +00:00
Ulya Trofimovich 3f3f0b73eb Prettified README somewhat. 2019-03-04 17:53:44 +00:00
Ulya Trofimovich a6462025af Moved LICENSE, README, NO_WARRANTY and CHANGELOG to the root directory. 2019-03-04 17:32:50 +00:00
Ulya Trofimovich 591c270770 Added license file. 2019-03-04 17:25:04 +00:00
Ulya Trofimovich 469fd0a7fb Deduplicated leftmost greedy closure implementations in re2c and libre2c. 2019-03-04 17:14:49 +00:00
Ulya Trofimovich 779747f709 Reuse second closure buffer as a stack for leftmost greedy closure. 2019-03-04 17:14:38 +00:00
Ulya Trofimovich ec5fddf9b9 Further deduplicated POSIX closure implementation in libre2c and re2c. 2019-03-04 15:52:16 +00:00
Ulya Trofimovich 2c2ed26277 Parameterized determinization/simulation context over history type. 2019-03-04 11:15:24 +00:00
Ulya Trofimovich b4d47abbf5 libre2c: parameterized context type over semantics (POSX/leftmost) and eval strategy (lazy/strict). 2019-03-02 10:31:17 +00:00
Ulya Trofimovich c2878dd100 Deduplicated POSIX closure computation in re2c and libre2c. 2019-03-02 09:10:51 +00:00
Ulya Trofimovich 2ed857ce6c libre2c: updated benchmark. 2019-03-01 22:40:23 +00:00
Ulya Trofimovich 6655ec2850 Deduplicated algorithm that computes POSIX precedence matrix in re2c and libre2c. 2019-03-01 22:15:34 +00:00
Ulya Trofimovich 8d1ed510d5 Deduplicated tag history definitions used in re2c and libre2c. 2019-03-01 10:55:38 +00:00
Ulya Trofimovich 23ff9e8206 Avoid allocating new scratch buffer for each closure, reuse the same buffer. 2019-02-28 10:57:10 +00:00
Ulya Trofimovich 8d46dc3a1c Exit early from loops in GOR1. 2019-02-27 11:46:55 +00:00
Ulya Trofimovich 5234b28815 libre2c: updated benchmark. 2019-02-27 11:28:33 +00:00
Ulya Trofimovich f33c3d99ab libre2c: use a more efficient algorithm for computing POSIX precedence matrix.
The old alrorithm was straightforward: it computed precedence for each
pair of core closure items. This has worst-case cubic complexity in the
size of TNFA, because closure can have O(N) states and tag history length
can be also O(N). One example is ((a?){1,1000})*.

The new algorithm avoids that by computing parecedence for all pairs of
core items in one traversal of the shortest path tree constructed by
closure. It avoids traversing deadend branches (those that were cancelled
by search because a better path was found) by marking used nodes of the
tree from each leaf down to the root. The new algorithm has worst-case
quadratic behaviour. It can be slightly slower for simple cases when the
number of core items is low and histories are short.
2019-02-27 10:50:07 +00:00
Ulya Trofimovich 47828ae1c9 Moved hot functions to header to enable inlining. 2019-02-27 10:44:15 +00:00
Ulya Trofimovich 5a59e5e33a libre2c (benchmark): do not try to link with re2 if it's not available. 2019-02-20 17:29:03 +00:00
Ulya Trofimovich c0c951cb78 libre2c: found pathological case for constant-memory POSIX algorithms.
The regexp is ((a?){1,200})*, and the input string is just "a".

Takes quibic time in the size of counter. This is caused by quadratic-
time computation of precedence matrix on each step (the number of TNFA
states in the closure approaches TNFA size), multiplied by the length
of compared histores (which also approaches TNFA size). Trie-based
algorithms are not affected, but they consume memory proportional to
the length of the input string, and so are also not practical.
2019-02-20 17:00:47 +00:00
Ulya Trofimovich bbe142c9c6 libre2c: added simplistic benchmark to compare different libre2c algorithms and re2. 2019-02-20 15:18:13 +00:00
Ulya Trofimovich f4303e1302 Simplification of GOR1 (following similar changes in libre2c). 2019-02-19 23:10:37 +00:00
Ulya Trofimovich 007c44ef3a No need to fully unwind tag histories when calculating POSIX precedence.
Histories are stored in a trie. Each history is represented by an index
to its tail in the trie. In order to compare two histories, we can simply
unwind both indices, step by step, until they coincide or root index is
reached.

Related commits in libre2c:
    062da2dca6
    2a7158b401
2019-02-19 21:51:43 +00:00
Ulya Trofimovich 914ec41242 libre2c: deleted unused buffers. 2019-02-19 21:44:38 +00:00
Ulya Trofimovich ba7a113b7a Use signed integers as tag history indices (this way root index -1 is the least one). 2019-02-19 21:40:46 +00:00
Ulya Trofimovich 62d3c51b70 run_tests.sh: ignore trailing whitespace in test diffs if compiler name matches "mingw".
We already ignore trailing whitespace when running in Wine, but binaries
that built with Mingw and run on windows (not in Wine) also need this option.
2019-02-19 17:52:36 +00:00
Ulya Trofimovich 55d651b7c4 Constified std::map comparator (apparently MSVC fails to compile otherwise).
Problem reported by Denis Naumov.
2019-02-19 16:51:02 +00:00
Ulya Trofimovich 1547049eb0 Correctly handle multi-character newlines (e.g. CR LF) when parsing #line directives.
Bug report thanks to Denis Naumov.
2019-02-19 16:40:19 +00:00
Ulya Trofimovich fd4957db85 libre2c: avoid -Wreturn compiler warnings (no return value from non-void function). 2019-02-19 15:59:20 +00:00
Ulya Trofimovich a8b21d60a1 libre2c: use core state indices when possible. 2019-02-19 14:22:40 +00:00
Ulya Trofimovich 5c74511af4 libre2c: inlined hot function. 2019-02-19 13:50:57 +00:00
Ulya Trofimovich e34298ab58 libre2c: updating marker of last matched rule after closure has been constructed (non-constant-memory version).
See commit 9998f616a3 (same for constant-memory version).
2019-02-19 13:49:19 +00:00
Ulya Trofimovich 062da2dca6 libre2c: compare histories in a trie without reconstructing them (non-constant-memory version.)
See commit 2a7158b401.
2019-02-19 13:33:45 +00:00
Ulya Trofimovich 32b0b91c94 libre2c: added forgotten file. 2019-02-19 12:43:27 +00:00
Ulya Trofimovich 0ecee64b46 libre2c: rearranged code to avoid checking configuration type when computing precedence matrix. 2019-02-19 12:12:46 +00:00
Ulya Trofimovich 41cdb935d2 libre2c: ensure TNFA simulation algorithms clean up context before exiting. 2019-02-19 12:03:12 +00:00
Ulya Trofimovich 44db77b7df libre2c: use templates to avoid dynamic dispatch between closure algorithms. 2019-02-19 08:49:27 +00:00
Ulya Trofimovich 662c7e8745 libre2c: hid some of the implementation details behind a pointer in regex_t struct. 2019-02-18 22:48:00 +00:00
Ulya Trofimovich 94a431f43a libre2c: simplified construction of configurations. 2019-02-18 22:15:50 +00:00
Ulya Trofimovich 338c852856 libre2c: added GOR1 algorithm for POSIX closure construction. 2019-02-18 21:44:29 +00:00
Ulya Trofimovich 2a7158b401 libre2c: compare histories in a trie without reconstructing them.
Previously we used to unwing each history, store it as a linear sequence
in a separate buffer, and then iterate buffers from the beginning of
histories to fing the fork point.

This reconstruction step can be avoided, because we can find fork by
tracing both histories together from tail to root, element by element,
until their indices coincide (this is the fork point. Someone called
thos "two-fingers algorithm".
2019-02-18 16:42:07 +00:00
Ulya Trofimovich e9799d313a libre2c: use signed indices in tag history (this way root index -1 is the least one). 2019-02-18 16:26:44 +00:00
Ulya Trofimovich e1760bd497 libre2c: marked hot function as inline. 2019-02-18 12:46:38 +00:00
Ulya Trofimovich 9998f616a3 libre2c: updating marker of last matched rule after closure has been constructed. 2019-02-18 12:36:40 +00:00
Ulya Trofimovich 5792868e4a libre2c: use lookahead to to filter leftmost closure before computing offsets. 2019-02-18 12:27:19 +00:00
Ulya Trofimovich a05480b129 libre2c: use lookahead to filter POSIX closure before computing offsets and precedence matrix.
This significantly reduces the amount of work on each step.
2019-02-18 12:27:04 +00:00
Ulya Trofimovich d01bdbb4c1 libre2c: implemented constant-memory (non trie-based) TNFA POSIX matching algorithm. 2019-02-18 11:33:10 +00:00
Ulya Trofimovich b4a2106513 libre2c: renamed a couple of struct fields (cosmetic). 2019-02-18 11:30:57 +00:00
Ulya Trofimovich fc9c8f63ab Correctly set values on main diagonal of POSIX precedence matrix (configuration compared to itself).
It doesn't show any difference on the tests, probably because previously
these values were set to zero, which unpacks to symmetrical (though
incorrect) values, and thus doesn't affect comparison.
2019-02-18 10:52:26 +00:00
Ulya Trofimovich 0afe383f2c libre2c: added (stub for) constant-memory (non trie-based) TNFA POSIX matching algorithm. 2019-02-14 13:35:58 +00:00
Ulya Trofimovich 971eedbf97 libre2c: use preallocated buffer. 2019-02-14 13:11:51 +00:00
Ulya Trofimovich baa24bdbd9 libre2c: added constant-memory (non trie-based) TNFA matching algorithm for leftmost greedy. 2019-02-14 13:11:27 +00:00
Ulya Trofimovich 77c669f64e Assign indices to core TNFA states (those that are final or have transitions on symbols).
During epsilon closure constructions, many operations only need to be
performed for core states. This allows to save some memory, e.g.
precedence matrix can be indexed by core states.
2019-02-14 12:52:50 +00:00
Ulya Trofimovich 8ec5890265 Structural tags are only needed for POSIX disambiguation, not for POSIX syntax. 2019-02-14 12:51:06 +00:00
Ulya Trofimovich 82e1db0e1c Added option --verbose that prints a message to stderr in case of success. 2019-02-13 15:27:55 +00:00
Ulya Trofimovich c4c996f59b Removed useless code in tests for misused option arguments. 2019-02-13 15:22:01 +00:00
Ulya Trofimovich 3f66fb7bba Tweaked error messages for misused option arguments, added some tests for them. 2019-02-13 14:33:39 +00:00
Ulya Trofimovich 7b96502e16 Added option --location-format <gnu | msvc> (default is gnu).
This option controls the formatting of locations in error messages
and warnings.

With --location-format gnu:

    filename:line:column: ...

With --location-format msvc:

    filename(line,column): ...
2019-02-13 13:50:00 +00:00
Ulya Trofimovich c52aa1bd5b Moved files. 2019-02-13 07:23:27 +00:00
Ulya Trofimovich dc9bdf960f Deduplicated filename strings in locations by interning them in a table and using indices. 2019-02-12 22:53:54 +00:00
Ulya Trofimovich 777476b0d8 Unified location handling by grouping relevant information in a struct.
Massive test updates are caused by refined locations for various error
messages and warnings (re2c now reports not only line, but also column).
2019-02-12 17:31:25 +00:00
Ulya Trofimovich de1414b6c0 Added test for EOF rule. 2019-02-11 21:43:52 +00:00
Ulya Trofimovich 11e548dc5f Use GNU-style location format 'file:line:column: ...' in warnings and error messages. 2019-02-11 13:11:47 +00:00
Ulya Trofimovich f16c5d9292 Added build script that uses '-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC'. 2019-02-09 18:20:23 +00:00
Ulya Trofimovich 82af4ae68e Fixed out of bounds read when sorting one-element initial closure.
The error only occurred on some libc implementations, e.g. on debug
glibc (options -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
2019-02-09 18:20:09 +00:00
Ulya Trofimovich 5b8611cdbe Fixed use of invalidated iterator after erase on std::map.
Problem reported by Denis Naumov.
2019-02-08 23:15:21 +00:00
Ulya Trofimovich 21a3df383b Use per-tag cache of history comparisons to avoid repeated computation. 2019-02-08 16:40:47 +00:00
Ulya Trofimovich 8838add4d5 Use counting sort for tag histories (the number tags is limited, so it is faster). 2019-02-08 16:08:58 +00:00
Ulya Trofimovich ad9438bd0a Use insertion sort instead of bubble sort (it is slightly faster). 2019-02-08 15:25:54 +00:00
Ulya Trofimovich d990c7a194 Fixed typo. 2019-02-08 13:58:43 +00:00
Ulya Trofimovich 2e8b959bcf Speedup in determinization (using a more efficient way to compare lookahead tags). 2019-02-08 10:59:58 +00:00
Ulya Trofimovich 88cd35eaf4 Yet another speedup in determinization (early exit when comparing history with itself). 2019-02-07 22:49:34 +00:00
Ulya Trofimovich f0006dcd6f Small speedup in determinization (by inlining small hot functions). 2019-02-07 22:06:40 +00:00
Ulya Trofimovich 885183b1de Small speedup in determinization by delaying computation of costly conditions. 2019-02-07 22:06:30 +00:00
Ulya Trofimovich e172628eae libre2c: added comment. 2019-02-07 11:31:47 +00:00
Ulya Trofimovich 4f30d79724 libre2c: speedup of POSIX NFA matcher by lazy computation and caching of precedence.
A lot of the match time was taken by eagerly computing precedence values
on each step for each pair of closure states. Most of these values are not
needed: RE may be unambigous; or the given input string may be unambigous,
even if there is ambiguity, it may take only a few comparisons to resolve.
All the rest is wasted effort.

We can avoid it by delaying precedence computation until necessary, and
then unwinding all the steps backwards, computing precedence for each step
and caching the computed values (so that the same pair of histories is not
compared twice). It is still the same incremental comparison as with
precedence matrices: we compare step by step, going from the fork frame to
the join frame. The result of comparison on each step is folded to a triple
of numbers and recorded in cache. It is important that we do record each
step, not just the first step, because the next pair of ambiguous histories
may unwind to the same pair of prefixes that was compared before.

For all this to work, it is necessary that we can store all history until
the very end, because at any step we might need to unwind an arbitrary
number of steps back. We also need to address individual subhistories
efficiently in order to use them as keys in the cache. All this is achieved
by storing history in the form of a trie and addressing individual
histories by indices in the trie. We also use trie to compute the resulting
tag values (instead of storing tags in registers at each step).
2019-02-07 10:50:35 +00:00
Ulya Trofimovich b8d938d9ac libre2c: small performance improvement in POSIX TNFA matcher. 2019-02-05 21:05:31 +00:00
Ulya Trofimovich e5ca515fe1 libre2c: extracted common parts of TNFA matchers (leftmost and POSIX). 2019-02-05 15:47:01 +00:00
Ulya Trofimovich c960cc011f libre2c: performance optimization: get all tag values in one scan of history. 2019-02-05 14:57:42 +00:00
Ulya Trofimovich fa0e0ade44 Renamed libre2c_posix -> libre2c (as it now also supports leftmost greedy semantics). 2019-02-05 13:33:04 +00:00
Ulya Trofimovich fd8278cc66 Differentiate between "POSIX syntax" and "POSIX semantics" options.
This is needed because we may want to use POSIX syntax with leftmost
greedy disambiguation. In that case, we still need parentheses-as-tags
attitude, but we don't want all the overhead and heuristics to spped
up POSIX closure.

libre2c_posix: added test for leftmost TNFA matcher.
2019-02-05 13:10:56 +00:00
Ulya Trofimovich 70e820cb20 libre2c_posix: added TNFA matcher with leftmost greedy disambiguation semantics. 2019-02-05 11:05:51 +00:00
Ulya Trofimovich 38450c5d69 libre2c_posix: small performance improvement in NFA-based matcher. 2019-02-02 19:08:45 +00:00
Ulya Trofimovich 4a97db297c libre2c_posix: added NFA-based matcher. 2019-02-02 18:16:32 +00:00
Ulya Trofimovich 5b7922312b Constified function parameter. 2019-02-02 18:12:18 +00:00
Ulya Trofimovich 33581fe5eb libre2c_posix: another small improvement in regexec() implementation. 2019-01-27 22:57:25 +00:00
Ulya Trofimovich 9bb25e426d libre2c_posix: a small performance improvement in regexec() implementation. 2019-01-27 18:05:23 +00:00
Ulya Trofimovich 25bef6f506 libre2c_posix: regex_t definition must be exposed to users.
POSIX standard says that:

    The regex_t structure is defined in <regex.h> and contains at
    least the following member: re_nsub (number of parenthesized
    subexpressions).
2019-01-27 17:50:37 +00:00
Ulya Trofimovich 4fa1bed013 libre2c_posix: enable tag optimizations. 2019-01-27 11:35:18 +00:00
Ulya Trofimovich 27c0562cbb libre2c_posix: extended regex_t structure to hold more submatch data.
Added fields:
    - re_nsub: total number of submatch groups, required by POSIX standard

    - pmatch: buffer for submatch results, usually supplied by the user to
      regexec(), but we allow to do the allocation and storage in regex_t.
      This is convenient for users that have hard time managing memory, e.g.
      java bindings to libre2c_posix.

    - regs: buffer for internal use by regexec(), strored in regex_t to
      avoid repeated memory allocation on each call to regexec() with the
      same regex.
2019-01-27 10:23:23 +00:00
Ulya Trofimovich b98e70f6a8 Adjusted build system to correctly build DLLs for windows.
Adjustments:
    - configure.ac:  pass win32-dll option to LT_INIT

    - Makefile_libre2c_posix.am: use -no-undefined in LDFLAGS

    - use slibtool: https://github.com/midipix-project/slibtool for windows
      builds The problem with libtool is that it doesn't allow to link libstdc++
      and libgcc statically, which is necessary to build portable DLLs with
      Mingw. Libtool adds -nostdlib option to LDFLAGS and links some predefined
      objects that pull in dependency on dynamic libstdc++ and libgcc, even in
      the presence of -static-libstdc++ -static-libgcc.
2019-01-27 10:06:22 +00:00
Ulya Trofimovich e686df8149 Use libtool to build libraries. 2019-01-19 11:57:16 +00:00
Ulya Trofimovich 4dea13a1c7 Fixed operator precedence with --flex-syntax option.
Operator precedence was broken because re2c tried to parse whole strings
of characters at once instead of parsing one character at a time (in
much the same way as it would parse properly quotes string literals in
the original re2c format). This caused ab* being parsed as (ab)*, which
is clearly wrong (should be a(b)*).

This fixes bug #242:
    "Operator precedence with --flex-syntax is broken."
2019-01-17 22:52:04 +00:00
Ulya Trofimovich b28b65ea40 libre2c_posix: handle empty group () in parser; added more tests. 2019-01-16 22:56:02 +00:00
Ulya Trofimovich 9c85f86b7e Make re2c:eof usable with push-model lexers (-f, --storable-state option). 2019-01-16 00:04:42 +00:00
Ulya Trofimovich 2af08e55d2 libre2c_posix: parse repetition counters in the lexer. 2019-01-15 00:24:22 +00:00
Ulya Trofimovich ef425c63d9 libre2c_posix: initial support for character classes in parser. 2019-01-14 23:04:23 +00:00
Ulya Trofimovich db4994c6c4 libre2c_posix (test): clear error status on expected failures. 2019-01-13 11:11:45 +00:00
Ulya Trofimovich ecffcea9bf libre2c_posix: skip fictive tags in regexec(); handle dot in parser; added more tests. 2019-01-13 10:57:53 +00:00
Ulya Trofimovich be3a711fb0 libre2c_posix: use C-array initializers instead of variadic functions for offset lists.
Variadic functions cause subtle toolchain-specific errors because integer
literals used to initialize offsets may have different type than the type
expected by variadic function (e.g. int vs long).
2019-01-12 20:32:15 +00:00
Ulya Trofimovich 9955713e8f libre2c_posix (test): a more concise error message. 2019-01-12 14:42:24 +00:00
Ulya Trofimovich d87aa779ec libre2c_posix: fixed -Wmaybe-uninitialized GCC warning. 2019-01-12 14:19:21 +00:00
Ulya Trofimovich 25c5e370e7 libre2c_posix: fixed memleaks. 2019-01-12 14:18:21 +00:00
Ulya Trofimovich 51d59d304b Experimental: initial implementation of libre2c_posix, POSIX regexp library based on re2c. 2019-01-12 12:50:47 +00:00
Ulya Trofimovich 1e80c5d54e Paper: don't forget to pass precedence matrices to initial closure. 2019-01-11 08:17:51 +00:00
Ulya Trofimovich 26ac83e39f Makefile.am: further simplify parser generation rules and avoid copying file to itself. 2019-01-11 00:34:07 +00:00
Ulya Trofimovich 2c51482092 Makefile.am: don't forget to run main test suite on make check. 2019-01-11 00:19:01 +00:00
Ulya Trofimovich 090cf99d72 Makefile.am: use more universal rules for autogenerated lexers and parsers. 2019-01-10 23:28:30 +00:00
Ulya Trofimovich eea66ec3fc Avoid unexpected removal of untracked files and directories. 2019-01-10 22:16:07 +00:00
Ulya Trofimovich 29c457c392 Moved function declarations to the header they belong in. 2019-01-10 22:09:25 +00:00
Ulya Trofimovich 6f2b7452a3 Updated range test. 2019-01-06 16:44:45 +00:00
Ulya Trofimovich 38dcc8ddc6 Use a simple fixed-size slab allocator for ranges. 2019-01-06 16:25:39 +00:00
Ulya Trofimovich 126940e33f Handle single chars and 1-char ranges in the same way. 2019-01-06 08:40:16 +00:00
Ulya Trofimovich 676ac74d9a Updated autogenerated files after change of directory layout. 2019-01-05 22:53:45 +00:00
Ulya Trofimovich ded5c7dfa8 Moved duplicated code into a separate function. 2019-01-05 22:49:52 +00:00
Ulya Trofimovich 2d4f7d740b Changed directory layout (cosmetic). 2019-01-05 22:41:45 +00:00
Ulya Trofimovich 7683f5601d Handle EBCDIC like other encodings instead of coupling it with character validation. 2019-01-05 13:16:36 +00:00
Ulya Trofimovich a1c1850419 Moved repeated code into a separate function. 2019-01-05 11:42:29 +00:00
Ulya Trofimovich c6f23fbc72 Fixed error in range difference with EBCDIC, added tests for various encodings. 2019-01-04 20:59:25 +00:00
Ulya Trofimovich c671813dc8 Compute range difference before applying encoding expansion to operands. 2019-01-04 19:41:38 +00:00
Ulya Trofimovich 2a56b5e18f Added test for bug #238. 2019-01-04 19:41:19 +00:00
Ulya Trofimovich fa912290f0 Fixed out-of-bounds write caused by misuse of slab allocator in case of large allocation size.
This fixes bug #238.
Found by american fuzzy lop (thanks to Henri Salo).
2019-01-04 13:14:23 +00:00
Ulya Trofimovich 6ca7c54d6e Adjusting formatting, dropping old macros (cosmetic). 2019-01-03 22:56:34 +00:00
Ulya Trofimovich a323015b1c Added tests for debug options. 2019-01-03 22:37:54 +00:00
Ulya Trofimovich f4bc9c11ba Added debug options --dump-cfg and --dump-interf. 2019-01-03 21:58:53 +00:00
Ulya Trofimovich 5bafe5be87 Moved debug stuff to a separate subdirectory. 2019-01-03 21:17:22 +00:00
Ulya Trofimovich ecc4ce6559 Disable --dump-* options in non-debug mode. 2019-01-03 20:28:48 +00:00
Ulya Trofimovich 3d9d43f94d Adding --enable-debug to Travis CI configuration. 2019-01-03 11:33:04 +00:00
Ulya Trofimovich 44536a04a9 Added some tests for GTOP closure algorithm. 2019-01-03 11:26:51 +00:00
Ulya Trofimovich b3bd138416 Added test comparing POSIX closure statistics with GOR1 and GTOP. 2019-01-03 11:13:15 +00:00
Ulya Trofimovich 6de83cb7d3 In debug build, add " (debug)" to version string. 2019-01-03 10:44:24 +00:00
Ulya Trofimovich 77b787ce5d Small simplifications in GOR1 initialization phase.
Instead of using two stacks to weed out low-precedence initial
configurations with duplicate target state, let them remain on the
bottom of topsort stack, which effectively makes them ignored.
2019-01-03 09:53:57 +00:00
Ulya Trofimovich c00037a72c Paper: simplifying GOR1 initialization pseudocode. 2019-01-03 09:45:54 +00:00
Ulya Trofimovich 476a546021 Small cosmetic simplifications in POSIX precedence. 2019-01-02 17:54:11 +00:00
Ulya Trofimovich d9d1a98751 Use a specialized simplified version of POSIX comparison for initial configurations. 2019-01-02 17:43:17 +00:00
Ulya Trofimovich 7f623ee597 Intrinsic options that do not have configurations should be immutable. 2019-01-01 21:19:49 +00:00
Ulya Trofimovich f3cee58b51 Added debug option --dump-closure-stats. 2019-01-01 21:19:43 +00:00
Ulya Trofimovich 3620765f62 Adjust TNFA construction for bounded repetition to the needs of GOR1. 2018-12-31 20:55:01 +00:00
Ulya Trofimovich 00e529ff45 Order initial configurations by POSIX precedence in GOR1. 2018-12-31 12:52:43 +00:00
Ulya Trofimovich 9d7922f4c4 Added option --posix-closure <gor1|gtop>. Removed configurations for internal options. 2018-12-31 12:37:12 +00:00
Ulya Trofimovich 93ad7ac245 Added GTOP SSSP algorithm for computing epsilon-closure with POSIX disambiguation.
GTOP SSSP meand "Global Topsort Single Source Shortes Path".

It is well known that SSSP can be solved in linear time on DAGs (directed
acyclic graphs) by exploring graph nodes in topological order. In our case
TNFA is not a DAG (it may have cycles), but it is possible to compute fake
topologcal order by ignoring back edges.

The algorithm works by having a priority queue of nodes, where priorities
are indices of nodes in fake topological ordering. At each step, the node
with the minimal priority is popped from queue and explored. All nodes
reachable from it on admissible arcs are enqueued, unless they are already
on queue.

The resulting algorithm is of course not optimal: it can get stuck on
graphs with loops, because it will give priority to some of the loop nodes
compared to others for no good reason.

However the algorithm is simple and optimal for DAGs, therefore we keep it.
2018-12-31 12:11:30 +00:00
Ulya Trofimovich d3753f304a run_tests.sh: cleanup .inc files. 2018-12-31 11:09:42 +00:00
Ulya Trofimovich 715ed1b422 Converting tabs to spaces (cosmetic). 2018-12-30 23:35:53 +00:00
Ulya Trofimovich f66853e57d Eh, some of the asserts were doing useful work and affecting control flow. 2018-12-30 23:30:28 +00:00
Ulya Trofimovich 0c8f6aaae9 Added assert wrapper that is turned on/off with --enable-debug configure option. 2018-12-30 19:53:46 +00:00
Ulya Trofimovich 89aed50410 Fixed errors in packing of signed integers. 2018-12-30 17:21:39 +00:00
Ulya Trofimovich 95e7a485c2 Reduce boilerplate in option parser with a few macros. 2018-12-30 11:42:38 +00:00
Ulya Trofimovich 662eb41b27 Use a couple of helper functions to make string construction easier. 2018-12-30 10:59:28 +00:00
Ulya Trofimovich 631429b6a6 Correctly parse -I option with or without space before the argument. 2018-12-30 10:30:19 +00:00
Ulya Trofimovich 136e617008 run_tests.sh: use paths relative to build directory, not to source directory.
Otherwise test results aren't reproducible: they depend on the
location of build directory relative to source directory.
2018-12-29 21:40:08 +00:00
Ulya Trofimovich 0051402976 Adding forgotten files to git. 2018-12-29 14:24:32 +00:00
Ulya Trofimovich c3c88aa65d More tests for include directive. 2018-12-29 14:17:31 +00:00
Ulya Trofimovich d1d1c926b4 Resolve names of included files relative to including file, not to the main file. 2018-12-29 00:16:53 +00:00
Ulya Trofimovich d9d8e93c19 Use correct order when unreading files from lexer buffer.
In lexer buffer nested files come before outer files. In lexer file
stack, however, outer files go before nested files (nested are at the
top). We want to break from the unreading cycle early, therefore we
proceed in reverse order of file offsets in buffer and break as soon
as the end offset is less than cursor (current position).
2018-12-29 00:06:28 +00:00
Ulya Trofimovich effc4a8944 Simplified lexing of include directive. 2018-12-27 22:50:00 +00:00
Ulya Trofimovich badd5f6b62 Tweaking a couple of labels in lexer to simplify updating of token pointer. 2018-12-27 22:42:06 +00:00
Ulya Trofimovich cc19421d70 Removed unused struct field. 2018-12-27 22:17:52 +00:00
Ulya Trofimovich 092e064173 Added test for EOF rule. 2018-12-27 22:10:49 +00:00
Ulya Trofimovich 8edf3ff252 Track current line of each input file separately. 2018-12-27 22:08:38 +00:00
Ulya Trofimovich 26230dd505 Correctly handle current directory '.' in include paths. 2018-12-26 20:12:51 +00:00
Ulya Trofimovich b94c5af9a2 Added -I option (paths to include directories). 2018-12-26 11:37:30 +00:00
Ulya Trofimovich df3949c6ee Added /*!include:re2c ... */ directive. 2018-12-25 19:53:23 +00:00
Ulya Trofimovich 1edd26a354 Preparations to support #include: keep input files in a stack. 2018-12-23 19:32:29 +00:00
Ulya Trofimovich f691f14f01 configure.ac: set -Wreturn-type to error. 2018-12-23 19:16:02 +00:00
Ulya Trofimovich f087e87268 Initial support of EOF rule. 2018-12-22 23:48:26 +00:00
Ulya Trofimovich a850df994e Updated unicode tests and test generators for newer versions of unicode. 2018-12-22 12:07:16 +00:00
Ulya Trofimovich b5471c4fca Paper: added two output() functions that convert t-string to parse tree and offsets. 2018-12-20 00:07:50 +00:00
Ulya Trofimovich 75a45812e0 Paper: tweaked TNFA construction. 2018-12-18 23:56:04 +00:00
Ulya Trofimovich 2f3e597abc Lexer: use YYMAXFILL padding and don't forget to shift tag variables in YYFILL.
This fixes bug #232, #233 and #234.
Found by american fuzzy lop (thanks to Henri Salo).
2018-12-06 22:03:34 +00:00
Ulya Trofimovich 69e9150365 Correctly identify mapped TDFA state with --dump-dfa-raw option. 2018-12-06 22:01:25 +00:00
Ulya Trofimovich 8d5e57f409 Makefile.am: enable RE2C warnings (-W option). 2018-11-29 22:21:43 +00:00
Ulya Trofimovich 4b511e541a Fixed read past the end of buffer in configuration parser.
This fixes bug #231.
Found by american fuzzy lop (thanks to Henri Salo).
Also reported by re2c -W (shame on me for not using it all this time!).
2018-11-29 22:15:18 +00:00
Ulya Trofimovich 91395ddd54 Paper: tweaking TNFA construction. 2018-11-26 22:58:14 +00:00
Ulya Trofimovich 15c5c7b41f Makefile.am: build autogenerates files before other targets (they may create headers).
Note: I used $(@:cc=*) construct as bmake doesn't understand $*.* .
2018-11-22 01:00:57 +00:00
Ulya Trofimovich c50f26462f Use tags to lex condition goto. 2018-11-21 22:04:19 +00:00
Ulya Trofimovich 41f67d75ff Started using tags in re2c own lexer. 2018-11-21 22:03:50 +00:00
Ulya Trofimovich c0ec8b25ba Removed redundant wrapper around output file struct. 2018-11-21 22:03:50 +00:00
Ulya Trofimovich f6dc93c88d Dump header on stdout if filename is not set, but /*!header:re2c:on*/ is used. 2018-11-21 22:03:50 +00:00
Ulya Trofimovich 553d228f99 Added configurations for -o, --output and -t, --type-header options. 2018-11-21 22:03:50 +00:00
Ulya Trofimovich 5b85eba0eb Added missing #line info after /*!header:re2c: ... */ directive.
Renamed:
    /*!header:re2c:1*/ -> /*!header:re2c:on*/
    /*!header:re2c:0*/ -> /*!header:re2c:off*/
2018-11-21 22:03:50 +00:00
Ulya Trofimovich 6f102a7961 Added /*!header:re2c:0*/ and /*!header:re2c:1*/ directives.
Combined with -t, --type-header option, this allows to put arbitrary
parts of the generated output in a header file.
2018-11-21 22:03:50 +00:00
Ulya Trofimovich 66a93ac35b Tweaking condition list lexer. 2018-11-21 22:03:50 +00:00
Ulya Trofimovich d364fc6ca5 Merge pull request #230 from sergeyklay/patch-1
Changes for upcoming Travis' infra migration
2018-11-21 21:54:58 +00:00
Serghei Iakovlev 39cbff2e12 Changes for upcoming Travis' infra migration
See: https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration
2018-11-21 22:23:09 +02:00
Ulya Trofimovich e566a24ae7 Fixed segfault cause by out of bounds access.
This fixes bug #227.
Found by american fuzzy lop (thanks to Henri Salo).
2018-11-15 07:33:25 +00:00
Ulya Trofimovich 3b685dac11 Moved tests into subdirectories. 2018-11-14 22:58:47 +00:00
Ulya Trofimovich 30a0682c03 Fixed a couple of lexer/parser errors in flex mode (-F option).
This fixes bug #229: re2c option -F (flex syntax) broken,
reported by Robert van Engelen.

A well-formed example that caused syntax error (flex-style raw literal
followed by one or more spaces and a curly brace):

/*!re2c
    a {}
*/

The faulty behaviour goes back as far as re2c-0.13.6 (and supposedly
before that): in flex mode, raw literal may occur in various contexts
both as a regexp (string literal) and an identifier (named definition,
condiiton name). RE2C uses lookahead to infer the context and determine
the appropriate type of lexer token, but it missed some cases.

The fix has two sides. First, if reduces the number of contexts where
the general lexer may encounter raw literal (by using specialized lexers
for condition lists <x,y,...,z> and condition goto => and :=>). Second,
it fixes the lookahead regexps used for context inference.

Also added a bunch of tests (generated by a script).
2018-11-14 00:01:51 +00:00
Ulya Trofimovich 5068fa4f18 Suppress -Wnullable warning on <> condition (it has no regexp -- always empty). 2018-11-13 23:38:02 +00:00
Ulya Trofimovich 40f22fa9f5 Adjusting formatting (cosmetic). 2018-11-05 23:35:11 +00:00
Ulya Trofimovich 5315a6db02 Fixed out of bounds read in configuration lexer (not handling EOF in configuration value).
Found by american fuzzy lop (thanks to Henri Salo).
2018-11-04 22:38:56 +00:00
Ulya Trofimovich c432c5c34c Small tweaks in lexer subroutines for semantic actions. 2018-11-01 00:01:25 +00:00
Ulya Trofimovich 0f7b449e01 Fixed yet another out of bounds read in lexer due to not handling EOF after escape.
Found by american fuzzy lop (thanks to Henri Salo).
2018-10-31 23:16:23 +00:00
Ulya Trofimovich f062a8bb82 Fixed some more out of bounds reads in lexer due to not handling EOF properly.
Found by american fuzzy lop (thanks to Henri Salo).
2018-10-30 22:11:32 +00:00
Ulya Trofimovich d6f9f21e44 Adjusted formatting in the lexer (cosmetic). 2018-10-29 23:32:22 +00:00
Ulya Trofimovich 44737d3792 Fixed out of bounds read in lexer.
The error was caused by assuming that a sequence of zeroes (used for
padding in YYFILL) cannot form a valid lexeme suffix. This is not the
case with strings, as they may contain arbitrary characters. The fix
is to manually loop over string characters in lexer, stopping at each
zero to check if it's the end of input.

Found by american fuzzy lop (thanks to Henri Salo).
2018-10-29 23:00:50 +00:00
Ulya Trofimovich ae2104669b Updated README in libre2c (added a warning that the library is not maintained). 2018-10-28 09:53:14 +00:00
Ulya Trofimovich 10ac1a2e46 Updated README. 2018-10-28 09:49:06 +00:00
Ulya Trofimovich 9a11d499d1 Paper: made TNFA description closer to practice. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 18579cc2c8 Paper: tweaks in the TNFA example. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich b315ecb78c Paper: changed description of GOR1 following the rework of the algorithm. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 27aadc4075 Paper: tweaks in picture layout. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 72febf2920 Paper: added TNFA example. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich a85dc05fbb Paper: added example for "empty match is better than no match" POSIX rule. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich c3acdca12a Paper: packed multiple examples of PE comparison in one page. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 184dd83e11 Paper: dropped explicit submatch indices in TNFA definition. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 96a1d27df4 Paper: handle (e) as (e){1,1} to avoid collapsing multiple submatch groups into one.
Previously we collapsed ((e)) into (e).
2018-10-28 09:40:19 +00:00
Ulya Trofimovich f577bb80b2 Paper: minor tweaks in pseudocode. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 464bee5e87 Paper: added description of GTOP closure algorithm. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 85753b63b0 Paper: made GOR pseudocode slightly easier to read. 2018-10-28 09:40:19 +00:00
Ulya Trofimovich 22b73edded Merge pull request #224 from trofi/master
src/dfa/closure_posix.cc: pack() tweaks
2018-10-22 23:33:02 +01:00
Sergei Trofimovich 7fb915b6e8 src/dfa/closure_posix.cc: fix pack() to drop two highest bits
```c
longest | (leftmost << 30);
```
assumes `longest` does not exceed 30 bits. It could if
it's a negative value originally.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-10-22 23:05:56 +01:00
Sergei Trofimovich 1b5a5f4449 src/dfa/closure_posix.cc: fix signed shift overflow
signed shift overflow is not defined by C standard.
clang++ -fsanitize=undefined detects it as:

```
src/dfa/closure_posix.cc:207:32: runtime error: left shift of negative value -1
```

This change wraps bit shift arithmetics into unsigned types.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-10-22 22:58:34 +01:00
Ulya Trofimovich 3425ce8479 Merge pull request #223 from metab0t/master
Fix typo
2018-10-17 23:29:07 +01:00
Nerd ad01d7c9b1 Fix typo 2018-10-17 16:23:22 +08:00
Ulya Trofimovich 141c0d8bad Merge pull request #222 from trofi/master
configure.ac: enable xz tarballs instead of gzip by default
2018-10-16 23:36:15 +01:00
Sergei Trofimovich 8cf9939c69 configure.ac: enable xz tarballs instead of gzip by default
`xz` compresses twice as good as `gzip` on `re2c` sources:

```
$ ls -lh *1.1.1*
4,8M re2c-1.1.1.tar.gz
2,5M re2c-1.1.1.tar.xz
```

Switch `make dist` to `xz by default. `gzip` is still available
via `make dist-gzip`.

Reported-by: rofl0r
Bug: https://github.com/skvadrik/re2c/issues/221
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-10-16 20:38:44 +01:00
Ulya Trofimovich eaa2ed61e3 Paper: added examples of the three rules of POSIX disambiguation. 2018-09-29 22:34:11 +01:00
Ulya Trofimovich 3634f584d1 Merge pull request #220 from trofi/master
src/dfa/dfa.h: simplify constructor to avoid g++-3.4 bug
2018-09-29 22:29:34 +01:00
Sergei Trofimovich 9efad4a550 src/dfa/dfa.h: simplify constructor to avoid g++-3.4 bug
On g++-3.4.6 re2c tests SIGSEGVed due to use of uninitialized data:

```
$ valgrind ... ./re2c -8 a.re -o foo.c
Conditional jump or move depends on uninitialised value(s)
   at 0x432F23: re2c::tcpool_t::insert(re2c::tcmd_t const*) (tcmd.cc:202)
   by 0x421FDA: re2c::freeze_tags(re2c::dfa_t&) (freeze.cc:45)
   by 0x43A7FF: re2c::ast_to_dfa(re2c::spec_t const&, re2c::Output&) (compile.cc:88)
   by 0x43B052: push_back (stl_iterator.h:614)
   by 0x43B052: re2c::compile(re2c::Scanner&, re2c::Output&, re2c::Opt&) (???:0)
   by 0x449D29: main (main.cc:31)
 Uninitialised value was created by a heap allocation
   at 0x403252F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x42FC9E: re2c::find_state(re2c::determ_context_t&) (dfa.h:37)
   by 0x429BD9: re2c::dfa_t::dfa_t(re2c::nfa_t const&, re2c::opt_t const*, std::string const&, re2c::Warn&) (determinization.cc:56)
   by 0x43A76C: re2c::ast_to_dfa(re2c::spec_t const&, re2c::Output&) (compile.cc:69)
   by 0x43B052: push_back (stl_iterator.h:614)
   by 0x43B052: re2c::compile(re2c::Scanner&, re2c::Output&, re2c::Opt&) (???:0)
   by 0x449D29: main (main.cc:31)
```

the problem here arose in default array constructor:

```c++
     explicit dfa_state_t(size_t nchars)
         : // ...
         , tcmd(new tcmd_t*[nchars + 2]()) // +2 for final and fallback epsilon-transitions
         // ...
```

g++-3.4.6 can't figure out zero-initialization rule (likely a gcc bug).

The change uses non-initializing new[] and memset() instead.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-09-29 22:26:19 +01:00
Ulya Trofimovich 858d6fb11c Merge pull request #216 from trofi/master
.travis.yml: run all tests behind 'make check'
2018-09-04 20:49:46 +01:00
Ulya Trofimovich 1c31284d70 Merge pull request #217 from trofi/add-msan
__alltest.sh: add clang's -fsanitize=memory flavour
2018-09-04 20:42:51 +01:00
Ulya Trofimovich a439ca0828 Fixed bug #215 "A memory read overrun issue in s_to_n32_unsafe.cc".
The error was in the code of the test itself: the special case of zero
wasn't handled correctrly by the function that prepares input data for
the test. As a result, zero-length input string was passed to the test,
which is unexpected: the tested function is an "unsafe" one (as the
name suggests) and is meant to be used on an already validated input.
2018-09-04 20:27:40 +01:00
Sergei Trofimovich d947ea3ea0 __alltest.sh: add clang's -fsanitize=memory flavour
Bug: https://github.com/skvadrik/re2c/issues/215
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-09-04 20:16:23 +01:00
Sergei Trofimovich 2c680453c5 .travis.yml: run all tests behind 'make check'
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-09-04 19:59:05 +01:00
Ulya Trofimovich d06bf2be1f Release 1.1.1. 2018-08-30 23:16:10 +01:00
Ulya Trofimovich 848ef0b837 Converted tabs to spaces in .re files and autogenerated files. 2018-08-30 23:11:00 +01:00
Ulya Trofimovich 15e02fccbf Updated CHANGELOG. 2018-08-30 23:00:56 +01:00
Ulya Trofimovich 2c461fe527 Makefile.am: reduced redundant variables. 2018-08-30 22:51:53 +01:00
Ulya Trofimovich b9b809ea22 Makefile.am: simplified clean-up part of bootstrap rule. 2018-08-30 22:45:04 +01:00
Ulya Trofimovich 9227fb1890 Rewrote version-to-vernum converter in RE2C; added more unit tests. 2018-08-30 22:38:42 +01:00
Sergei Trofimovich c17fa5aa48 vernum: move version-string-to-vernum converter to a separate helper
No functional change. While at it added tests
to cover past failures:
- "1.1": https://github.com/skvadrik/re2c/issues/211
- "0.14": https://sourceforge.net/p/re2c/bugs/55/

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2018-08-29 07:12:06 +01:00
Mike Gilbert 348d8689be Rewrite vernum function
Fixes: https://github.com/skvadrik/re2c/issues/211
2018-08-28 20:19:13 +01:00
Ulya Trofimovich ab647f6b53 Release 1.1. 2018-08-27 22:44:50 +01:00
Ulya Trofimovich 553a6610d2 Regenerated docs. 2018-08-27 21:55:29 +01:00
Ulya Trofimovich 0d2a4e0cb9 Updated CHANGELOG. 2018-08-27 21:55:24 +01:00
Ulya Trofimovich b158b2d5e6 Paper: more tweaks in examples of trace computation. 2018-08-27 21:26:56 +01:00
Ulya Trofimovich 9c2a55c7ff Increase allocator alignment to pointer size to avoid unaligned reads/writes.
Unaligned operations found by ubsan.
2018-08-14 07:10:26 +01:00
Ulya Trofimovich 464ab8c5a8 Fixed memory corruption bug (caused by wrong size passed to memcpy).
Found by asan.
2018-08-13 23:43:06 +01:00
Ulya Trofimovich 79dc58fb2f Reordered function definitions. 2018-08-13 23:21:57 +01:00
Ulya Trofimovich 74724a9d93 Moved different closure construction algorithms to separate files. 2018-08-13 23:11:42 +01:00
Ulya Trofimovich b267cb922c Moved POSIX disambiguation algorithm to a separate file. 2018-08-13 23:02:01 +01:00
Ulya Trofimovich cc1ae4e877 Converted tabs to spaces. 2018-08-13 22:49:44 +01:00
Ulya Trofimovich 87514d62b4 Renamed a couple of structs. 2018-08-13 22:43:16 +01:00
Ulya Trofimovich 251f292c2b Merged a couple of small headers into one. 2018-08-13 22:05:40 +01:00
Ulya Trofimovich 80eab69573 Gathered all determinization-related data in a struct to avoid passing many parameters. 2018-08-12 21:07:12 +01:00
Ulya Trofimovich 24142df77d Use fixed 32-bit indices in lookup tables instead of 'size_t'. 2018-08-12 20:28:09 +01:00
Ulya Trofimovich 0f571df54f Moved all notes (lengthy comments with names) to the beginning of file. 2018-08-11 09:01:57 +01:00
Ulya Trofimovich df98d5e10a Rearranged the code a bit with a couple of helper subroutines. 2018-08-11 00:59:09 +01:00
Ulya Trofimovich e8c01cfc2d Don't use a dedicated struct for returning multiple values from function. 2018-08-11 00:32:11 +01:00
Ulya Trofimovich 12818c6fde Simplified back up / restore of tag actions when mapping TDFA states. 2018-08-11 00:13:04 +01:00
Ulya Trofimovich 6a2acd23f9 Gathered various buffers used for TDFA state mapping in a struct. 2018-08-10 06:57:05 +01:00
Ulya Trofimovich 0fa8fbacac Use somewhat more consistent variable naming. 2018-08-09 22:28:41 +01:00
Ulya Trofimovich 3b27f67096 Replaced Kuklewicz POSIX disambiguation algorithm with Okui algorithm.
Changes in the test results are caused by putting negative tags of the
right alternative *before* the alternative.
2018-08-09 21:46:30 +01:00
Ulya Trofimovich 9ab3663e89 Pack tag index and sign into one 32-bit field. 2018-08-06 22:37:38 +01:00
Ulya Trofimovich ee309d076f Compute and store tag "height" (needed for Okui disambiguation). 2018-08-06 20:08:30 +01:00
Ulya Trofimovich 3f5fa5cc4e Always add structural tags to the RHS of alternative/catenation in POSIX captures.
(Preliminary work before switching from Kuklewicz POSIX disambiguation
algorithm to Okui algorithm.)
2018-08-04 10:44:56 +01:00
Ulya Trofimovich 328788acce Don't move the closing tag of POSIX capture group out of the enclosing iteration.
RE2C used to perform the following optimization: when a POSIX capture is
under iteration, we only need to get tag values of the last iteration
(according to the POSIX standard). Therefore we can move the closing tag
out of loop.

This commit removes this optimization (as part of the effort to switch
from Kuklewicz POSIX disambiguation algorthm to Okui algorithm).

In other words, for RE (x)* re2c used to generate this "optimized" IRE:
    1 (3 x)* 4 2
and now it generates the "canonical" IRE:
    1 (3 x 4)* 2

Updated tests for '--posix-captures' that have been affected by the change.
2018-08-04 10:25:01 +01:00
Ulya Trofimovich 4a3e72bf9e Allow default copy for POD struct (fixes [-Wclass-memaccess] GCC warning). 2018-08-04 10:09:01 +01:00
Ulya Trofimovich 05d5c5959f Updated GOR1 (fixed the core algorithm to avoid useless re-scans of the same state).
Also, depth-first traversal was done in a slightly incorrect way:
we checked outgoing nodes for admissibility and pushed the corresponding
child states on stack all at once. This is not the same as checking
the first child and recursing into it, then checking the next child,
..., and so on (because we might discover the second child while exploring
the first, and admissiblitiy check for the second child *after* that
might yield false, while *before* exploring the first child it yielded
true).
2018-07-28 23:30:04 +01:00
Ulya Trofimovich bf658a52d2 Pick the shortest available path suffix when generating skeleton path cover.
This also fixes a error in the generation process: sometimes in case
of loops the current node's suffix was set before all of its children
were processed.

Updated test results (in some cases .input files became larger because
of the above fix, in some cases they became smaller because we now pick
the shortest suffix).

Added new test; this one was found by slyfox's fuzzer and revealed the
above bug.
2018-07-28 22:52:44 +01:00
Ulya Trofimovich 26bd896717 Changed the name of a local variable in the test to avoid collision with skeleton names.
Before tags were added to re2c, skeleton programs only used a limited
number of predefined names, such as 'yych', 'yystate', etc. With tags,
however, this is no longer true as tags may have any names. So now we need
to be more cautios when picking names for sekleton variables.

This patch is only a workaround to make all tests pass; the real solution
requires inventing a good naming scheme for skeleton programs and
regenerating all skeleton test results.
2018-07-28 10:53:34 +01:00
Ulya Trofimovich 52709d8e61 Paper: more tweaks of GOR1. 2018-07-28 10:36:08 +01:00
Ulya Trofimovich c4ee5ea622 Fixed error in calculation of maximal skeleton path length.
The error was found by slyfox's fuzzer (a randomly-generated skeleton test).

The bug in the code was, apparently, too early modification of the state's
estimated maximal distance to the end states: the distance was set before
all of the state's children were processed, which resulted in aborting the
accumulation of distance from the remaining children, and, as a consequence,
shorter than necessary max distance for the root itself.
2018-07-28 10:21:37 +01:00
Ulya Trofimovich 6f1d5f97ee Paper: updated version of GOR1. 2018-07-25 22:35:31 +01:00
Ulya Trofimovich e9fa1cc91c Paper: some tweaks for the examples of traces computation. 2018-07-07 00:01:15 +01:00
Ulya Trofimovich 6b73d5ec83 Paper: another example of traces computation. 2018-07-02 23:06:40 +01:00
Ulya Trofimovich eb94bfe01f Paper: added example of PEs and traces computation. 2018-06-30 21:23:13 +01:00
Ulya Trofimovich 96aea70f17 Fixed processing of #line directives in input files.
The correct behaviour was broken somewhere in between 0.16 and 1.0:
re2c was forgetting to output the chunk of input file that precedes
the #line directive.

Reported by pskocik in #98.
2018-06-25 23:18:54 +01:00
Ulya Trofimovich 5034ea4cd8 Paper: re-worked the theorem about compatibility of total and partial orders. 2018-06-24 23:06:06 +01:00
Ulya Trofimovich a7b548a13b Paper: started re-working the theorem about compatibility of total and partial orders. 2018-06-24 09:37:48 +01:00
Ulya Trofimovich 241458d1e0 Paper: made example about parse trees consistent with its description. 2018-06-23 11:06:02 +01:00
Ulya Trofimovich 6db0f0c8d6 Paper: continued restructuring the part about indexed parse trees. 2018-06-23 10:57:58 +01:00
Ulya Trofimovich 5fc6441626 Paper: restructured the IRE construction example. 2018-06-20 22:29:17 +01:00
Ulya Trofimovich c83179e53b Paper: added an example of IRE construction. 2018-06-18 23:14:22 +01:00
Ulya Trofimovich c39391d857 Paper: added introduction to the second chapter. 2018-06-17 10:21:02 +01:00
Ulya Trofimovich 30ff06d02e Paper: revise basic definitions before introducing partial order on trees. 2018-06-16 10:47:54 +01:00
Ulya Trofimovich 5946a0e900 paper: taken care of Angelo's remarks. 2018-06-13 23:01:25 +01:00
Ulya Trofimovich 25c327f598 Added option "--conditions" (an alias for "-c" and "--start-conditions").
Fixes issue #206 "wrong long option for -c mode".
2018-06-11 21:27:27 +01:00
Ulya Trofimovich 36737173bf Added first part of TDFA paper v2. 2018-05-24 23:44:23 +01:00
Ulya Trofimovich bda341ad66 Improved error reporting in fuzz-testing script. 2018-04-25 22:49:15 +01:00
Ulya Trofimovich fe4bf2e385 If the input starts with a re2c block, apply re2c configurations immediately. (see #201). 2018-04-14 21:50:32 +01:00
Ulya Trofimovich 4a614d6007 Escape backslashes in file names (see #201). 2018-04-14 00:23:35 +01:00
Ulya Trofimovich bf573bbac1 Release 1.0.3. 2017-11-08 20:40:53 +00:00
Ulya Trofimovich 5b95c8ed0a Fix for #198.
GCC-4.2.1 is unable to compile code like this:

    std::vector<int> v;
    std::vector<int>::const_reverse_iterator i;
    for (i = v.rbegin(); i != v.rend(); ++i) ;

It's unable to deduce const overload for 'rend':

    "no match for ‘operator!=’ in ‘i != std::vector<_Tp, _Alloc>::rend()"

However, the following code compiles fine:

    std::vector<int> v;
    std::vector<int>::const_reverse_iterator i = v.rbegin(), e = v.rend();
    for (i != e; ++i) ;

This was reported by Ryan Shmidt.
2017-11-08 07:19:21 +00:00
Ulya Trofimovich e313dd2e31 Fixed typo in docs (found by Maxim Reznik). 2017-09-14 20:08:37 +01:00
Ulya Trofimovich 4300196e8f Removed unaccurate example.
Parsing floating-point numbers is hard and re2c doesn't help much,
so this example was somewhat misleading.
2017-08-28 17:33:46 +01:00
Ulya Trofimovich 8fff3d07da Release 1.0.2. 2017-08-26 21:07:06 +01:00
Ulya Trofimovich 63b441de4b Updated changelog. 2017-08-26 21:02:22 +01:00
Ulya Trofimovich 090353cd2a Some more fixes to the documentation. 2017-08-26 20:26:26 +01:00
Ulya Trofimovich 98ab529614 Updated documentation. 2017-08-26 19:10:24 +01:00
Ulya Trofimovich 947d65d02e Disallow condition names and named definitions to start with digit.
This has always been the intended behavior and was accidentally broken
by commit e3db638fc3.
2017-08-26 10:51:56 +01:00
Ulya Trofimovich 5d43d423e7 Renamed tests. 2017-08-22 21:39:33 +01:00
Ulya Trofimovich 8ac9292416 Updated examples and added them to 'run_tests.sh' script. 2017-08-22 18:06:55 +01:00
Ulya Trofimovich b3de182666 Updated changelog. 2017-08-22 09:15:47 +01:00
Ulya Trofimovich 9a0b9603d2 Added forgotten 'genhelp.sh' to distribution files.
This fixes bug #194 "Build with "--enable-docs" fails".
2017-08-22 09:09:35 +01:00
Ulya Trofimovich aca702d0a7 Added examples to test suite. 2017-08-18 16:09:59 +01:00
Ulya Trofimovich 6152e0280f Added benchmarks to test suite. 2017-08-16 18:43:13 +01:00
Ulya Trofimovich d106039ec4 Updated changelog for 1.0.1 version. 2017-08-11 22:43:05 +01:00
Ulya Trofimovich e58939b34b Release 1.0.1. 2017-08-11 22:31:09 +01:00
Ulya Trofimovich b64c45e0a5 Makefile.am: add paper on Lookahead TDFA to distribution. 2017-08-11 22:16:04 +01:00
Ulya Trofimovich 2aae99cd95 Fixed #193: "1.0 build failure on macOS: error: calling a private constructor of class 're2c::Rule'".
Copy constructor and assignment are requred by std::valarray
implementation on macOS.
2017-08-11 22:04:05 +01:00
Ulya Trofimovich 9b57a424be Release 1.0. 2017-08-11 14:46:23 +01:00
Ulya Trofimovich ff730d071b Paper on lookahead TDFA: finished. 2017-08-11 12:52:10 +01:00
Ulya Trofimovich 625a991585 Updated help and manpage. 2017-08-10 16:03:46 +01:00
Ulya Trofimovich ecf949ec41 Leave the definition of 'yynmatch' and 'yypmatch' to the user.
With '--posix-captures' RE2C stores submatch results in 'yynmatch'
(the total number of capturing groups for the matching rule) and
'yypmatch' (an array of submatch values for each group).

These variables should be user-defined, so that users can override
default implementation (e.g. make 'yypmatch' an array of integer
offsets rather than an array of pointers). Overriding is only possible
with generic API: if default API is used, then RE2C can autogenerate
'yynmatch' and 'yypmatch' (and so it did prior to this commit).
However, it is better to have the same behavior with both APIs; also,
it is coherent with '--tags' option (RE2C leaves tag definition to
the user).
2017-08-10 13:25:07 +01:00
Ulya Trofimovich f962589e25 Updated options list and regenerated docs. 2017-08-09 18:35:15 +01:00
Ulya Trofimovich 7c55550852 Added short option '-P' corresponding to '--posix-captures'. 2017-08-09 18:07:50 +01:00
Ulya Trofimovich 5f0e7f8ff0 Fixed includes with 'include-what-you-use'.
Command:

    $ configure CXX=include-what-you-use CXXFLAGS="--check-also" \
        && make -k 2>log \
        && python2 `which fix_inclydes.py` < log
2017-08-09 17:17:09 +01:00
Ulya Trofimovich 42a3461201 Paper on Lookahead TDFA: added bibliography. 2017-08-09 14:04:10 +01:00
Ulya Trofimovich 95deb6e70a Amended README instructions for benchmarks. 2017-08-09 09:46:59 +01:00
Ulya Trofimovich be6bb0fd96 Paper on Lookahead TDFA: added pictures. 2017-08-07 12:59:05 +01:00
Ulya Trofimovich bb3cb82877 Paper on Lookahead TDFA: fixed captions and ran through aspell. 2017-08-07 12:54:29 +01:00
Ulya Trofimovich a626fc5dc1 Paper on Lookahead TDFA: added benchmark results and graphs. 2017-08-05 09:33:30 +01:00
Ulya Trofimovich 81236bfe26 Paper on Lookahead TDFA: reformatted examples. 2017-08-04 09:57:58 +01:00
Ulya Trofimovich 2526526a3d Tweaked CXXFLAGS in asan build script. 2017-08-04 09:54:20 +01:00
Ulya Trofimovich 937f24b41d A small tweak in benchmarking scripts that reduces warmup time. 2017-08-04 09:50:59 +01:00
Ulya Trofimovich f20d1a0520 Fuzzers: a bunch of small tweaks. 2017-08-03 12:14:19 +01:00
Ulya Trofimovich dc2495c680 Skeleton: fixed initialization of maximal path length.
Broken by commit fffb5932ee.

Path length were initialized with 0 instead 'DIST_ERROR', which caused
incorrect calculation of maximal path length. This in turn caused errors
in estimating the number of byted necessary to hold keys during data
generation in skeleton. The resulting keys were one-byte while maximal
path length was more than one byte, which (fortunately!) caused runtime
errors in skeleton programs.

Example of program that caused skeleton error:
    /*!re2c
        (@t [\x00] [^]{5,6})* {}
    */

The error was hidden for so long because in practice inputs that need
more than one-byte keys are rare, and fuzzer sets 'ulimit -t 10' when
running re2c, so most of such programs were simply aborted. Those that
were not aborted still had a chance of estimating key size correctly.
2017-08-03 12:00:32 +01:00
Ulya Trofimovich ea25db593e Fixed cppcheck 'style' warnings.
Used the following command to run cppcheck:

   cppcheck --enable=all --inconclusive --std=posix --quiet --force -I. src/
2017-08-02 23:11:13 +01:00
Ulya Trofimovich 35352054a9 Fixed headers that were not self-contained.
Used the following command to find errors:

    for h in $(find src/ -name '*.h*'); do echo "CHECKING $h"; g++ -I. -c $h -o foo.o; done
2017-08-02 21:43:36 +01:00
Ulya Trofimovich 024c5236ff Benchmarks: added README and small samples of input data. 2017-08-02 18:07:16 +01:00
Ulya Trofimovich d60509ee84 Added scripts that run benchmarks. 2017-08-02 16:06:32 +01:00
Ulya Trofimovich 5417c0baab Added fuzzers (contributed by Sergei Trofimovich). 2017-08-01 16:41:58 +01:00
Ulya Trofimovich e5e182ff95 Don't loose mtag versions in TDFA intitalizer. 2017-08-01 16:36:45 +01:00
Ulya Trofimovich cd48d98b34 Makefile.am: use portable POSIX primitive to get directory name.
Use '$(@D)' instead of '$(dir $@)', as the latter requires secondary
expansion feature specific to GNU make; it causes build failures on
bmake.

'$(@D)', on the other hand, is a POSIX make feature documented e.g. in
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html
(section "Internal Macros").
2017-08-01 13:19:06 +01:00
Ulya Trofimovich edd3180406 Added some testing scripts for various CXX/CXXFLAGS confgurations. 2017-08-01 12:51:19 +01:00
Ulya Trofimovich af3a69bf7e Makefile.am: fixed other custom rules to avoid writing into unexistent directory.
The fixed rules do not presently trigger any build errors: target directory
is created by configure as it need to put autogenerated files doc/manpage.rst
and doc/help.rst in it.

However, this behaviour is occasional: if one removes the .in files, build
failure would be unmasked. So it makes sense to ensure that target directory
exists.
2017-08-01 11:39:39 +01:00
Ulya Trofimovich f4734c4ff7 Makefile.am (building docs): create target directory before writing into it.
To reproduce build falure (before the fix):

    $ mkdir <builddir>
    $ cd <builddir>
    $ ../condigure --disable-dependency-tracking
    $ make src/conf/help.cc V=1
    cp ../bootstrap/src/conf/help.cc src/conf/help.cc
    cp: cannot create regular file ‘src/conf/help.cc’: No such file or directory
    Makefile:1984: recipe for target 'src/conf/help.cc' failed
    make: *** [src/conf/help.cc] Error 1
2017-08-01 11:19:27 +01:00
Ulya Trofimovich 00a0b8b073 Makefile.am (rebuilding docs): create target directory before writing into it.
To reproduce build falure (before the fix):

    $ mkdir <builddir>
    $ cd <builddir>
    $ ../condigure --disable-dependency-tracking --enable-docs
    $ make src/conf/help.cc V=1
    rst2man.py ./doc/help.rst > src/conf/help.cc.1
    /bin/sh: src/conf/help.cc.1: No such file or directory
    Makefile:1976: recipe for target 'src/conf/help.cc' failed
    make: *** [src/conf/help.cc] Error 1
2017-08-01 11:09:03 +01:00
Ross Burton 5f7169690a Makefile.am: create target directory before writing into it
In some situations src/parse/ may not exist before a file is copied into the
directory. Ensure that this doesn't happen by creating the directory first.
2017-08-01 10:19:15 +01:00
Ulya Trofimovich a62c8f0814 Don't assert that comparator arguments are non-equal.
Comparator is used in 'std::sort'.
All items in closure have unnique TNFA states, therefore we assumed
that the compared items must always be different. However, 'std::sort'
does not have this requirement and some implementations of it compare
the element with itself.

The removed assert caused crashes with old version of GCC (4.2).

Thanks to Sergei Trofimovich for debugging the issue.
2017-08-01 08:22:14 +01:00
Ross Burton 1e0a00dea4 Makefile.am: create target directory before writing into it
In some situations src/parse/ may not exist before a file is copied into the
directory. Ensure that this doesn't happen by creating the directory first.
2017-07-31 15:45:37 +01:00
Ulya Trofimovich 38480968f0 run_tests.sh: avoid using 'sed -i' as it is non-portable.
On FreeBSD 'sed -i' works in a different way than on Linux.
2017-07-31 15:05:44 +01:00
Ulya Trofimovich c253f9bd1a Use explicit stack instead of implicit recursion.
With CXXFLAGS='-fsanitize=addres' GCC complains about stack overflow.
2017-07-31 14:22:19 +01:00
Ulya Trofimovich c7b8af0f61 Fixed unaligned memory access.
With CXXFLAGS='-fsanitize=undefined' GCC complains about unaligned access:
if custom allocator is used to allocate structs or other alignment-sensitive
things, then it must take care of the alignment (for example, add padding
to all unaligned blocks of memory which it allocates).
2017-07-31 13:59:51 +01:00
Ulya Trofimovich d0dfcc2bb9 Avoid calling 'memcpy' to copy zero bytes from NULL source.
With CXXFLAGS='-fsanitize=undefined' GCC complains about passing NULL
pointer to function which parameter is marked as 'attribute__((nonnull))'.
2017-07-31 13:58:19 +01:00
Ulya Trofimovich 5d44c6d4fa Fixed MINGW warnings. 2017-07-31 12:40:07 +01:00
Ulya Trofimovich 71b8897ebd Added some more suggestions for pre-release testing. 2017-07-31 12:03:28 +01:00
Ulya Trofimovich efa9dc302c Fixed GCC warnings with '-m32'. 2017-07-31 11:49:20 +01:00
Ulya Trofimovich dc372de134 Fixed some of the warnings that Clang emits with '-Weverythng'. 2017-07-31 11:29:36 +01:00
Ulya Trofimovich 7b65aa15b3 Merge remote-tracking branch 'origin/devel'. 2017-07-30 21:51:31 +01:00
Petr Skocik 4e4352a98c fix documentation issue #184 2017-07-30 21:11:02 +01:00
Ulya Trofimovich 10ed477d72 Manpage: removed occasionally copy-pasted section. 2017-07-30 21:10:31 +01:00
Ulya Trofimovich b15338a799 Autogenerate help from manpage. 2017-07-30 21:10:14 +01:00
Ulya Trofimovich 739d2b7df8 Manpage: include paths must be relative to 'top_srcdir'.
Otherwise out-of-source builds won't work.
2017-07-30 21:07:25 +01:00
Petr Skocik 68775ac3f6 compose manpage out of rsts from gh-pages-gen 2017-07-30 21:06:46 +01:00
Petr Skocik ac6ca8f514 sync --help output w/ manpage
+ set output width to 80
    + make help output go to stdout rather than stderr
2017-07-30 21:04:24 +01:00
Petr Skocik 6eafc7bedb Grammar fixes in the manpage 2017-07-30 21:03:46 +01:00
Ulya Trofimovich f6cb83dadc Recognize newlines in character strings and classes.
As for now, newline inside of a character string or class is an error:
re2c should emit clear error message. Different styles of newlines
should be recognized ("\n", "\r\n").

This commit fixes bug #162 reported by pauloscustodio:
    Reading files with "rb" causes issues in Windows
2017-07-30 18:08:38 +01:00
Ulya Trofimovich 6831c35f53 Fixed line endings in output files on Windows (#162, #163).
This fix consists of two issues, both reported and fixed by pauloscustodio.

1. #162 "Open text files with "wb" causes issues on Windows"

    Text files need to be opened for writing with "w", so that stdio does
    the right thing in respect to the correct line endings for the current OS.
    ("\r\n" in Windows, "\n" in Linux).

2. #163 "Reading files with "rb" causes issues in Windows"

    re2c reads input files in binary mode and writes the generated output in
    text mode. This caused CR LF conversion to CR CR LF on Windows: first CR
    comes from reading input in binary mode, second CR is added when writing
    output in text mode. This only happened to those parts of input which are
    not transformed by re2c: we used to copy-paste verbatim, now we patch line
    endings. Now we convert all line endings to LF before writing the generated
    code to file.
2017-07-30 17:45:30 +01:00
Ulya Trofimovich 20dc41d6cd Fixed #147 "Please add symbol name to "can't find symbol" error message".
As suggested by sirzooro:
    Please add symbol name to "can't find symbol" error message,
    it would allow to quickly spot what is wrong. Now we have to
    position cursor at given row and column to find that name.

Also tweaked error reporitng function to append "..." at the end
of the message if it didn't fit into buffer.
2017-07-30 16:21:21 +01:00
Ulya Trofimovich f3f08578cc Fixed bug #145 "Values for enum YYCONDTYPE are not generated
when default rules with conditions are used".

Default rule is handled in a special (delayed) way;
re2c uses different code for default rule than for normal rules.
This special code simply forgot to add condition name to the list
of conditions.

Thanks to sirzooro for bug report.
2017-07-30 16:00:19 +01:00
Ulya Trofimovich e1c56a8e07 run_tests.sh: fix permissions after copying source files to build directory.
`make distcheck` protects source files from writing.
Test script run_tests.sh copies source files into build directory,
but the copied files inherit permissions, so `make distcheck` fails.
2017-07-30 12:00:31 +01:00
Ulya Trofimovich 0877b20e34 run_tests.sh: patch line endings in the generated file.
Line endings in the generated code depend on the target platform: e.g.,
"\r\n" on Windows vs. "\n" on Linux. However, reference test results are
(currently) generated on Linux and therefore contain "\n" line endings.
So we have to patch line endings in the generated code in order to pass
the tests on Windows.

Testing script did patch line endings in stdout and stderr, but forgot
to patch them in the generated file (it was broken since we started to
use '-o' option for testing). This commit fixes testing script.

It also deletes a couple of tests in which source code contains "\r\n"
instead of "\n". These tests are duplicates of other tests (they were
added by commit bd2875441c supposedly to
test that re2c preserves line endings in source code). They are broken
by current commit and fixing them is probably not worth of the effort.
2017-07-30 11:58:27 +01:00
Ulya Trofimovich eb58cfee71 Fixed #141 "Tests under Windows".
Thanks to Abs62, who noted that under Windows (in MSYS) tests fail
because '2>"$outc.stderr"' dumps CRLF to file instead of LF
and proposed a fix:
    sed -i 's/\r//g' "$outc.stderr"
2017-07-30 11:48:31 +01:00
Ulya Trofimovich cb6d309cc3 Makefile.am: removed inexistent header. 2017-07-30 11:46:31 +01:00
Ulya Trofimovich fee5e9e4ea Updated paper on Lookahead TDFA. 2017-07-29 19:27:32 +01:00
Ulya Trofimovich e8e7235e52 Explicitly pass line/column info in all error messages.
Updated tests. Some error messages are more precise now, e.g. ill-formed
character classes and escape sequences: column points to the beginning
of the faulty lexeme rather than to the middle of it where the error
occured. Other error messages are less precise (lack column info), but
the column reported before was too inexact and didn't make much sense.
2017-07-29 19:10:44 +01:00
Ulya Trofimovich 695d6a3840 Renamed simple tags into 'stags' and tags with history into 'mtags'.
YYTAGP                  -> YYSTAGP
YYTAGN                  -> YYSTAGN
YYTAGLISTP              -> YYMTAGP
YYTAGLISTN              -> YYMTAGN
/*!tags:re2c ... */     -> /*!stags:re2c ... */
/*!taglists:re2c ... */ -> /*!mtags:re2c ... */

Updated tests and benchmarks.

Fixed warning message in '-Wnondeterministic-tags'.
2017-07-28 16:08:14 +01:00
Ulya Trofimovich ca9f601f16 POSIX disambiguation: use the same comparison algorithm for orbit and non-orbit tags.
Previously we needed a different algorithm for non-orbit tags, because
disambiguation was based on both start and end tags. Non-orbit start tags
cannot be compared incrementally, like orbit tags, becuse default value
may be discovered on a later step than non-default value. Non-orbit end
tags do not have this problem: since negative tags are inserted at the end
of alternatives, default value is always discovered on the same step as
non-default value (provided that all higher-priority tags agree and
comparison reaches this tag at all).

Now that start tags are ignored, we can use incremental comparison for both
orbit and non-orbit subhistories, which simplifies the code.
2017-07-28 11:17:10 +01:00
Ulya Trofimovich ebbbcb1569 Paper on Lookahead TDFA: added benchmarks. 2017-07-19 18:43:33 +01:00
Ulya Trofimovich 15e063d7fc Reset '--no-lookahead' to default value if '--tags' is not enabled. 2017-07-18 13:56:48 +01:00
Ulya Trofimovich eaefa16b33 Apply tag version compaction even with '--no-optimize-tags'.
Otherwize RE2C emits too many unused tag variables and bloats the generated code.
2017-07-18 13:54:46 +01:00
Ulya Trofimovich 13a93f126f Split source file in two. 2017-07-18 08:56:22 +01:00
Ulya Trofimovich de9ec18a14 Replaced configuration 'no-lookahead' with 'lookahead' and updated test. 2017-07-17 23:07:44 +01:00
Ulya Trofimovich d2ff88bf53 Added option '--no-optimize-tags' (switches off tag optimizations). 2017-07-17 23:03:53 +01:00
Ulya Trofimovich d87e64b0c1 Fixed memory leak. 2017-07-17 22:38:20 +01:00
Ulya Trofimovich ddb3d85078 Forbid merging of tag variables for tags with and without history. 2017-07-17 22:36:02 +01:00
Ulya Trofimovich 52ad8ae802 Added directive '/*!taglists:re2c ... */' to handle tags with history.
It is exactly like '/*!tags:re2c ... */', except that the latter is for
simple tags, while the former is for tags with history.
2017-07-16 12:13:04 +01:00
Ulya Trofimovich facb5e1acd Paper on Lookahead TDFA: added section about implementation. 2017-07-12 17:42:34 +01:00
Ulya Trofimovich b969741167 Nicer output with '--dump-dfa-raw' and '--dump-nfa'. 2017-07-12 17:39:03 +01:00
Ulya Trofimovich 6279a08034 Allocate final/fallback tag versions beforehand.
Just a more clear and intuitive way to allocate them, and easier
to document. Updated a lot of tests; changes are trivial.
2017-07-11 16:12:21 +01:00
Ulya Trofimovich aedfc8db0c First part of the paper on Lookahead TDFA. 2017-07-10 14:43:28 +01:00
Ulya Trofimovich 90e5120cbd Nicer output with '--dump-dfa-raw' and '--posix-captures'.
Don't add closure items to "shadowed" set if there is an identical
"unshadowed" item: otherwise Goldberg-Radzik algorithm generates too much
"shadowed" items and the output becomes too noisy.
2017-07-07 22:42:08 +01:00
Ulya Trofimovich cf96e3cdb9 Use different closure algorithms for leftmost greedy and POSIX policies.
With leftmost greedy policy we can use simple depth-first search.
With POSIX policy we need Goldberg-Radzik algorithm, which is more complex
(and the necessity to accommodate both policies complicates it even more).
2017-07-07 15:16:16 +01:00
Ryan Mast 2d8def82ca Fix for possible invalidated iterator after resize 2017-07-02 22:11:32 +01:00
Ryan Mast fa60d948df Add const to newver_t operator()
A certain set of compilers gives a compiler error due to losing
"const-volatile qualifiers"
2017-07-02 09:30:12 +01:00
Ulya Trofimovich 7897755dc2 Allow trivial cycles (of length 1) in tag commands.
We forbid cycles of length 2 or more because they would need temporary
variable local to the basic block, which would complicate liveness
analysis. However, trivial cycles don't need a temporary.
2017-07-02 09:05:29 +01:00
Ulya Trofimovich d09777244f Fixed typo that caused miscalculation of new tag version. 2017-06-27 15:40:42 +01:00
Ulya Trofimovich 1702e39906 Invert comparison result instead of negating its arguments. 2017-06-27 14:14:33 +01:00
Ulya Trofimovich 7d6934e691 Skip (non-orbit) start tags during POSIX disambiguation.
Their position is fixed on some higher-priority tag (except the very
first tag, but in RE2C match is always anchored).
We cannot skip orbit start tag because the corresponding orbit end tag
is hoisted out of loop (by construction) and is, in fact, non-orbit.
2017-06-27 14:05:26 +01:00
Ulya Trofimovich 5f78312b92 Once again fixed history comparison for POSIX disambiguation. 2017-06-27 13:53:09 +01:00
Ulya Trofimovich 97d04e39cb Use Goldberg-Radzik shortest path algorithm for closure construction.
It has O(M*N) worst-case complexity, where M is the number of nodes (states)
and N is the number of arcs (transitions).

Papers: 1993, "A heuristic improvement of the Bellman-Ford algorithm"
by Goldberg, Radzik and 1996, Shortest paths algorithms: Theory and
experimental evaluation" by Cherkassky, Goldberg, Radzik.
2017-06-06 11:27:15 +01:00
Ulya Trofimovich 68a88d109e Compare full tag histories, not just the last subhistories.
Comparing the last pair of subhistories is not enough: because of
the shortest-path algorithm mismatch may occur at some earlier point
(not at the last pair), in which case we still need to re-run the search.
2017-06-05 22:17:40 +01:00
Ulya Trofimovich 5ada82171a Simplified queue handling in epsilon-closure algorithm. 2017-05-24 11:21:48 +01:00
Ulya Trofimovich b226458522 Use the same comparison functions for closure construction and order calculation. 2017-05-22 14:51:05 +01:00
Ulya Trofimovich d62aa9f33d Use two tags instead of three for captures under iteration.
Before we simplified POSIX disambiguation by inserting missing
captures, using three tags to represent captures under iteration
was the only way: we needed to guard where the first iteration starts,
where the last iteration starts and where the last iteration ends.
Therefore we used three tags: opening, closing and orbit.

Now that we insert missing pieces of capture hierarchy, we no longer
need a special opening tag for captures under iteration: there always
is a higher-priority tag that guards the start of the first iteration.

Massive test updates are mostly due to the fact that orbit tag is no
longer fixed (fixed tags go in the end): ~100 out of 147 tests.
Some other ~45 tests have two tag variables flipped. There are 4 tests
with non-trivial changes. All updated tests pass POSIX test
(/test/posix_captures/.run/__run.sh).
2017-05-21 10:07:58 +01:00
Ulya Trofimovich 5fdc5de763 Silenced '-Wnondeterministic-tags' warning with '--posix-captures'. 2017-05-20 19:11:19 +01:00
Ulya Trofimovich 8df712898a Skeleton should ignore fictive tags.
The combination of options '--skeleton' and '--posix-captures'
didn't work properly.
2017-05-19 22:36:25 +01:00
Ulya Trofimovich f5671eb722 Forbid mixing leftmost greedy and POSIX disambiguation.
Mixing doesn't make much sense (there is no obvious use case).
It might be possible, but for now better forbid it before someone
starts to use it and it turns out to be impossible or very complex.
2017-05-19 22:11:24 +01:00
Ulya Trofimovich 733494c2e1 Simplified POSIX disambiguation by reconstructing capture hierarchy.
POSIX treats captured and non-captured subexpressions on equal terms.
However, non-captured subexpressions have no tags to guard them.
Previously we used default tags to infer ambiguous paths that correspond
to the missing captures: if one path had default tag and the other did
not, then desicion which path is better was made according to the leftmost
strategy. This algorithm works because in POSIX expressions without
captures have the property that leftmost path is the best path (for
example, 'a?' is greedy, it means 'a or epsilon').

However, this algorithm has one downside: because we may need leftmost
comparison, we have to impose leftmost order on NFA substates of each
DFA state, as well as maximize and orbit order for tags. This prevents
us from mapping perfectly mappable DFA states and we end up with a larger
DFA (which is sometimes folded back to smaller DFA, but not always).

Also, default-leftmost algorithm is more complex than inserting missing
hierarchy pieces: proving that it works is non-trivial.
2017-05-19 08:47:36 +01:00
Ulya Trofimovich e53781621b Fixed history comparison in case both latest subhistories are bottoms.
In this case, instead of comparing histories by the leftmost criterion
(as it should be, if only one of them is bottom), we should assume that
from standpoint of this tag histories are equal and move on to other
tags.
2017-05-16 22:11:55 +01:00
Ulya Trofimovich 51fe1a5b45 Avoid exponential blowup in tagged epsilon-closure construction.
The previous algorithm waited until the full epsilon-path is built,
then compared it to already existing paths. The new algorithm compares
and merges partial epsilon-paths as soon as they arrive at the same
NFA state, so the overall number of paths is bounded by the number of
NFA states at all times.
2017-05-16 18:46:08 +01:00
Ulya Trofimovich 194d41a76a Don't split tag history into individual sub-histories for tags.
This is necassary for correct comparison of orbit tag histories:
if orbit tag is nested in an outer capture, this outer capture is
under repetition and there is an epsilon-path through it, then
this epsilon-path may contain pieces of orbit history that belong
to different iterations of outer capture; these pieces will be
glued together and the boundary between them will be lost.

Example: ((""){0,3}){0,2}.

However, in a common history we can always find boundaries
(they are marked by tags that correspond to outer captures).
2017-04-29 21:13:50 +01:00
Petr Skocik 43681dc4d7 fix documentation issue #184 2017-04-20 17:06:17 +01:00
Ulya Trofimovich 81b416d508 Skeleton: constified tag variables to get rid of compiler warning. 2017-04-16 12:36:44 +01:00
Ulya Trofimovich b6b65d49fc Command normalization: update pointer to last command, it might change.
If normalization of 'save' commands removes the last 'save' command,
then pointer to 'next' will point to the 'next' field of the removed
command and the chain of commands will break.
2017-04-16 11:10:25 +01:00
Ulya Trofimovich f38f819072 Added comment. 2017-04-16 11:10:03 +01:00
Ulya Trofimovich 92058c5ce5 release.sh: added cppcheck and headers check to wish list. 2017-04-16 11:09:15 +01:00
Ulya Trofimovich 6d15ecc5ef Forbid dependency cycles in tag commands.
The previous attempt was to forbid 2-cycles; clearly it's not enough
and cycles of length greater than 2 also pose a problem.

We could allow cycles and deal with them by introducind a temporary
variable. However, this would create variables local to basic blocks,
which would complicate liveness analysis and dead code elimination.
2017-04-14 18:47:11 +01:00
Ulya Trofimovich 4909060f34 Tag interference analysis: compare actual values, not formal RHS.
Commands in the same basic block may have equal right hand sides,
e.g. 'x = y; z = y;'. Clearly in this case 'x' and 'z' do not interfere:
both versions are equal to 'y'. This optimization allows to deduplicate
cases like '("a" @x @y @z "b")*', where multiple tags have the same
values.

However, it is insufficient to find all commands in the current block
with RHS equal to current RHS. An example when this algorithm fails:
'x = y; w = z; z = y;', here 'x' and 'z' are assigned to the same RHS
'y', but if we merge them into one variable, 'w' will get the wrong
value.

The fix is as follows: first, ignore subsequent commands and consider
only commands that precede current command: if subsequent command that
sets LHS to the same value precedes any use of it, liveness propagation
through basic block would mark this LHS as dead and not interfering
anyway; otherwise (if use precedes setting to the same value), then it
indeed interferes with current LHS. This fixes the above example
'x = y; w = z; z = y;': when analysing 'x = y;' command we find that
'z' is alive (as before), but ignore subsequent 'z = y;' command (due
to the fix).

Second, when analysing preceding commands, calculate actual value for
each LHS (based on pessimistic assumption that on entry of basic block
all used versions are different). Formal RHS of some preceding command
may coincide with current formal RHS, but their values might differ:
'x = y; y = w; z = y;', here 'x = y;' and 'z = y;' have identical formal
RHS, but the value may be different. On the other hand, formal RHS
might be different, while their actual values are equal, as in
'x = y; w = y; z = w;'.
2017-04-14 12:03:07 +01:00
Ulya Trofimovich 1807b3275f Skeleton: don't forget to return error in case of tag mismatch. 2017-04-13 11:02:35 +01:00
Ulya Trofimovich 9cc1d42cea Final tag versions in unreachable rules should be marked as unused. 2017-04-12 13:26:15 +01:00
Ulya Trofimovich 90a63934b5 '--dump-adfa': fixed pretty-printing of tag commands. 2017-04-12 12:06:17 +01:00
Ulya Trofimovich e96798acde Preserve order of commands when adding fallback tags. 2017-04-12 12:05:13 +01:00
Ulya Trofimovich 1a31f17aa0 Added debug for tag optimizations (CFG and interference table). 2017-04-12 11:26:18 +01:00
Ulya Trofimovich 07a95ea519 Record full history for history-based tags on epsilon-paths. 2017-04-12 10:24:34 +01:00
Ulya Trofimovich 53748ee115 Keep tag histories for the whole time of determinization. 2017-04-11 10:45:19 +01:00
Ulya Trofimovich a0f8c1392c Manpage: removed occasionally copy-pasted section. 2017-04-10 13:43:02 +01:00
Ulya Trofimovich f9a34baf88 Autogenerate help from manpage. 2017-04-10 13:41:17 +01:00
Ulya Trofimovich e5c74f4f0c Manpage: include paths must be relative to 'top_srcdir'.
Otherwise out-of-source builds won't work.
2017-04-09 19:36:28 +01:00
Ulya Trofimovich 26a22a2d90 run_tests.sh: fix permissions after copying source files to build directory.
`make distcheck` protects source files from writing.
Test script run_tests.sh copies source files into build directory,
but the copied files inherit permissions, so `make distcheck` fails.
2017-04-09 19:28:28 +01:00
Petr Skocik b0e3de4107 compose manpage out of rsts from gh-pages-gen 2017-04-09 14:54:30 +02:00
Ulya Trofimovich 3245d8da9e Topsort: always initialize in-degree with zeroes.
Don't rely on the fact that topsort leaves all-zero in-degree:
it doesn't if cycles are present. One could manually zero the remaining
entries after topsort, but zero initialization is more reliable.
And it's quite efficient since we only need to initialize the entries
we use.
2017-04-08 23:04:48 +01:00
Ulya Trofimovich 059b10f5b4 Don't forget final and fallback commands when looking for history-based tags. 2017-04-08 19:58:50 +01:00
Ulya Trofimovich 25d0a5d71a Merged a couple of slightly different 'topsort' versions into one. 2017-04-08 19:37:32 +01:00
Ulya Trofimovich 9cfa0ca3c9 'save' commands also need topological sorting: they may depend on history. 2017-04-08 11:35:14 +01:00
Ulya Trofimovich 2d145e666f When mapping states, avoid double substitution in 'save' commands.
When mapping states, we need to create a list of 'copy' commands.
However, if there is a 'save' command with LHS equal to RHS of the 'copy'
command, then instead of the 'copy' command we just fix LHS of the 'save'
command, as explained in this note:

    /* note [save(X), copy(Y,X) optimization]
     *
     * save(X) command followed by a copy(Y,X) command can be optimized to
     * save(Y). This helps reduce the number commands and versions (new version
     * X is gone), but what is more important, it allows to put copy commands
     * in front of save commands. This order is necessary when it comes to
     * fallback commands.
     *
     * Note that in case of injective mapping there may be more than one copy
     * command matching the same save command: save(X), copy(Y,X), copy(Z,X).
     * In this case save command must be replicated for each copy command:
     * save(Y), save(Z).
     *
     * For each save(X) command there must be at least one copy(Y,X) command
     * (exactly one case of bijective mapping). This is because X version in
     * save(X) command must be a new version which cannot occur in the older
     * DFA state. Thus all save commands are transformed (maybe replicated) by
     * copy commands, and some copy commands are erased by save commands.
     *
     * This optimization is applied after checking priority violation, so it
     * cannot affect the check.
    */

However, the previous implementation would sometimes erroneously re-fix
the already fixed 'save' commands. This patch rewrites it in a way that
avoids re-fixing.
2017-04-08 09:46:41 +01:00
Petr Skocik 107a30b3d4 sync --help output w/ manpage
+ set output width to 80
    + make help output go to stdout rather than stderr
2017-04-08 01:29:51 +02:00
Ulya Trofimovich 27958784e2 Fixed checking duplicates when creating tag commands. 2017-04-07 22:36:20 +01:00
Ulya Trofimovich a43d840244 Don't forget histories when comparing right hand sides of tag commands. 2017-04-07 18:49:58 +01:00
Ulya Trofimovich 9483b682b2 Skeleton: don't emit declarations for tags that are optimized out. 2017-04-07 17:19:09 +01:00
Ulya Trofimovich 558752b873 Don't forget initial tag command when looking for history-based tags. 2017-04-07 17:17:56 +01:00
Ulya Trofimovich e034325622 Tag histories in commands must be addressed by absolute value. 2017-04-07 17:00:14 +01:00
Ulya Trofimovich 1f7aa3594d Don't sort and deduplicate 'save' commands for tags with history.
Otherwise chains like '2=(1,x); 1=(1,y)' will be rewritten to
'1=(1,y); 2=(1,x)', which is a totally different thing.
2017-04-07 16:44:44 +01:00
Ulya Trofimovich a50862bb60 'save' commands for tags with history may need fallback copies.
For simple tags without history 'save' command is self-sufficient:
it does not depend on anything. However, for tags with history 'save'
commands depend on history, which may be overwritten on the way from
accepting state to fallback transition. We must take care and backup
such overwritten histories when leaving the accepting state.

If history is not overwritten, we don't need a copy, but we still
have to propagate its liveness forward on all fallthrough paths
outgoing from accepting state.
2017-04-07 16:19:00 +01:00
Ulya Trofimovich f038ddc908 Added skeleton support for tags with history. 2017-04-07 16:01:23 +01:00
Ulya Trofimovich 19f460cf8f Fixed order of tag commands.
First, fallback 'copy' commands should go before 'save' commands.
Second, codegen should not reorder 'copy' and 'save' commands.
These two bugs shadowed each other and everything seemed to work.
2017-04-06 18:08:04 +01:00
Ulya Trofimovich bc0fde95fc Changed generic API for tags.
- removed 'YYCOPYTAG', use simple assignment insted
      (it is hard to think of any other definition)
    - renamed 'YYBACKUPTAG' to 'YYTAGP'
    - added 'YYTAGN', 'YYTAGLISTP', 'YYTAGLISTN'
    - removed 're2c:tags:default' configuration
2017-04-06 17:45:42 +01:00
Ulya Trofimovich c04ebbb5da Added codegen primitives for tags with history. 2017-04-06 15:18:12 +01:00
Ulya Trofimovich 503b393867 Fixed tag optimizations to respect tags with history. 2017-04-06 08:29:24 +01:00
Ulya Trofimovich 2a5fe439b0 Added syntax for tags with history. 2017-04-05 20:45:42 +01:00
Ulya Trofimovich d58c90b50b Started to add optional history for each tag.
This patch adds tracking and saving tag history during determinization;
however, optimizations and codegen totally neglect histories.
2017-04-05 17:01:54 +01:00
Ulya Trofimovich a693598540 Separated lookahead tags from tag versions in closure items.
This commit reverts commit 0b2ca9bf14:
"Pack lookahead tags together with tag versions in TDFA state."

Packing was possible because we were not interested in tag version
if closure item had this tag in lookahead set. However, if we are
to store the full history of each tag, we'll need this intermediate
version in spite of the fact that it is overwritten on the next
transition.
2017-04-05 12:50:24 +01:00
Petr Skocik 511bf66dbe more manpage fixes 2017-04-04 15:08:00 +02:00
Ulya Trofimovich 55853fdc01 Fixed liveness analysis inside of basic block.
Liveness flows backwards through basic block, so it should be
propagated backwards starting with live-out set and applying
commands one by one in reverse order.
2017-04-04 13:41:41 +01:00
Ulya Trofimovich 10803f4e2b Merge 'save' and 'copy' command lists into one common list.
Previously we used separate lists for them; however the structure
of 'save' and 'copy' commands is almost identical, so its easy to
use one C struct for both types. Also, this simplifies analysis:
both types of commands are handled in a uniform way.

However, now we have to do list transformations like sorting and
deleleting duplicates in chunks.

This is a preliminary step to allow intermixing 'copy' and 'save'
commands.
2017-04-04 08:25:34 +01:00
Petr Skocik 438aa27f7e Grammar fixes in the manpage 2017-04-03 17:48:10 +02:00
Ulya Trofimovich 7944e06363 Explicitly track order of closure items for leftmost disambiguation.
Before this commit leftmost order was maintained implicitly by construction
of closure: NFA is traversed in left-first order, so the earliest item added
to closure is also the leftmost. Special care was taken to preserve this
order and never rearrange closure elements.

This is convenient if leftmost disambiguation strategy is the only one.
However, other strategies require explicit bookkeeping of disambiguation
information (POSIX needs tag history for orbit tags, maximize/minimize
needs most recent tag versions). Implicit handling of leftmost strategy
does not fall in line with other strategies.

By tracking leftmost order explicitly we achieve several goals:
    - uniform handling of disambiguation strategies
    - DFA states can be treated as good old sets again, which is more
      conventional and means less work for minimization

POSIX tests changed (but the '/test/posix_captures/.run/__run.sh' script
still passes all tests) because there was an error in the order items were
added to closure, which probably prevented minimization (if the new item
dominated the existing one, the old one was substituted with the new one,
while it should have been removed and the new one appended at the end).

Skeleton tests changed because the order of NFA states in DFA state does
not matter, so more states can be merged by determinization.
2017-03-17 08:25:24 +00:00
Ulya Trofimovich 685c038d46 Forbid 2-cycles in tag commands; fixed topsort to skip cycles. 2017-03-08 14:16:19 +00:00
Ulya Trofimovich 7ecdfd8263 Moved a couple of files. 2017-03-08 08:48:30 +00:00
Ulya Trofimovich eba6b926fb Moved the main driver out of parser grammar file. 2017-03-08 08:32:16 +00:00
Ulya Trofimovich f9fd740f3b Split options into constant and mutable; restricted access to mutable ones.
Some options are immutable (target, output files; global switches like
conditions, reuse mode, storable states; support of flex syntax, etc.).
These options are passed as command-line arguments and never change.
It is safe to read them from any program point after parsing command-line
arguments.

Other options are configurable; they have block scope (may be specified
anywhere inside of the block and still affect the whole block).
Reading mutable options of yet unparsed block is not allowed because
they may affect the way RE2C parses current block (RE2C would be tempted
to base decisions on the latest option value, which may not be the final
one).
2017-03-07 21:57:05 +00:00
Ulya Trofimovich 93e30f3407 Forbid configuration of certain options.
Configuration of these options either makes little sense (like changing
target on the fly) or is technically impossible to implement (the only
example is '-F, --flex-syntax' option which non-trivially affects the way
RE2C parses programs).
2017-03-07 18:51:29 +00:00
Ulya Trofimovich ecd3b24982 '-Wcondition-order': check '-t, --type-header' option together with other conditions. 2017-03-07 18:43:05 +00:00
Ulya Trofimovich 6e0cc064c1 Moved enum out of struct and added prefix 'TARGET_' to all members. 2017-03-07 18:23:24 +00:00
Ulya Trofimovich ac079a3dc2 Delay check if tags are allowed until the whole block has been parsed. 2017-03-07 18:16:56 +00:00
Ulya Trofimovich ec3bf59e1e Now that we never re-parse anything we can always dicard old data. 2017-03-07 18:07:09 +00:00
Ulya Trofimovich 021242bdb2 Tests for POSIX captures: avoid using 'flags:flex-syntax' configuration.
Use '--flex-syntax' command-line option instead.

The actual tests are not changed by this commit.
2017-03-07 17:57:48 +00:00
Ulya Trofimovich d362068fd0 Allow to set new encoding without explicitely resetting the current one. 2017-03-07 17:52:42 +00:00
Ulya Trofimovich df22475551 More elegant handling of flex definitions. 2017-03-06 21:42:05 +00:00
Ulya Trofimovich f8ebfc977d Check precondition inside of the function rather than at every call site.
Changes in tests are caused by the lack of newline after '/*!ignore:re2c*/'
directive. There's no particular reason why it should be emitted and RE2C
code is simpler without it.
2017-03-06 21:33:17 +00:00
Ulya Trofimovich f45600b6c1 Gathered all error checking related to '-r' option in one place. 2017-03-06 11:25:13 +00:00
Ulya Trofimovich e80bf0bdd7 Moved remaining option-sensitive code away from AST.
AST must be immutable and independent of options: it may be shared among
different blocks and conditions and reused with different options.
2017-03-06 08:54:10 +00:00
Ulya Trofimovich 73f87e144e Merged small header with part of AST into big header with the whole AST. 2017-03-05 11:51:30 +00:00
Ulya Trofimovich fc93270e94 Renamed 'RegExp' to 'AST'. 2017-03-05 11:43:26 +00:00
Ulya Trofimovich 7903c55c9c Don't ever reparse '/*!rules:re2c ... */' block.
AST is immutable and independent of options: encoding expansion and other
option-sensitive transformations are delayed until AST is converted to
intermediate representation. Thus AST can be shared among different blocks
and conditions and reused with any set of options without modifications.

Changes in tests are trivial: warnings from the rules block are no longer
emitted (we don't compile AST to DFA for rules block anymore, since it
will be discarded anyway); skeleton tests no longer emit '.input' and
'.keys' files for rules block.
2017-03-05 10:43:54 +00:00
Ulya Trofimovich 858b1c7b2a Restructured source files layout. 2017-03-04 23:27:52 +00:00
Ulya Trofimovich cd6209e66a Delay encoding expansion until AST is converted to intermediate representation. 2017-03-04 22:54:22 +00:00
Ulya Trofimovich 41c925b852 Store locations in AST so that error reporting does not depend on parser.
This allows us to delay things that should be delayed (like expanding
regexps with respect to current encoding), but which may throw an error
and need location info.
2017-03-04 17:00:59 +00:00
Ulya Trofimovich 0c1e034856 Added test for '--posix-captures': implicit grouping is forbidden.
RE2C has named definitions, which allow to override operator precedence
without grouping parenthesis. However, in POSIX all parenthesis are
capturing: allowing some of them to be non-capturing would affect
disambiguation and might result in a different parse.

For now RE2C uses a crude criterion to determine if the given named
definition needs to be explicitely wrapped in parenthesis: if the topmost
constructor of the subexpression is either alternative, or catenation, or
another reference to another named definition, then wrapping is required.
This is an overapproximation, because it doesn't take the surrounding context
into account (e.g. catenation inside of an alternative doesn't need wrapping,
but catenation inside of an iteration does).
2017-03-04 12:09:40 +00:00
Ulya Trofimovich 0b962be858 Added tests for POSIX captures.
Tests are adopted from Glenn Fowler's testregex suite and its derivative
regex-posix-unittest by Christopher Kuklewicz.

Irrelevant tests have been dropped:

    - tests for specific POSIX features not supported by RE2C, like
      begin/end markers '$' and '^', backreferences, predefined character
      classes (most of them come from 'basic' subdirectory)

    - all 'leftassoc' tests: they are exact copies of 'rightassoc' tests,
      differ only in match results and are supposed to fail

    - all tests from 'categorize' that are supposed to fail

I also added a few tests of my own (in the 'other' subdirectory).

Tests are arranged as a bunch of '.dat' files (each file contains lines of
the form '<regexp> <string> <match>' or blank lines) and two scripts.

    - '__run.sh' runs all tests (generates temporary '.re' file with the
      given regexp, compiles it, runs against the given string and checks
      that the result coincides with the given result)

    - '__gen.sh' regenerates '.re' files for regular RE2C test suite (the
      generated files do not contain any code, just the bare regexp)

All regexps are pre-patched to exclude '\x00' (terminating NULL) character
from subregexps like '.' or '[^a]: otherwise RE2C-generated programs would
greedily consume all characters and fail. Note that if only '.' was present
in the original tests, we might have used '\n' as terminator, but '[^a]'
includes newline. Also '()' subregexp was substituted with '("")'.
2017-03-04 11:48:49 +00:00
Ulya Trofimovich 882e3ec821 '--skeleton --posix-captures': use correct capture index when checking tags.
Instead of skipping fixed tags, skip orbit tags. For each orbit tag there is
a tag fixed on it, so if we check all fixed tags we'll surely check all orbit
tags. Anyway, with '--skeleton' all fixed tags correspond to orbit tags: other
fixed tags are forbidden with generic API (even zero-offset ones for now).
2017-03-03 23:09:19 +00:00
Ulya Trofimovich 3423797445 Remove dead 'copy' commands.
For some reason dead code elimination pass simply ignored 'copy' commands
and removed only dead 'save' commands. Strange as it seems, this went
unnoticed until now (when one of the POSIX tests compiled into C++ code
that triggered GCC warning about use of uninitialized variable).
2017-03-03 17:27:35 +00:00
Ulya Trofimovich 742f67921d Fixed code generation for '--skeleton' with '--posix-captures'. 2017-03-03 17:06:31 +00:00
Ulya Trofimovich 81c3bdab1d Added option '--posix-captures'.
With this option re2c interprets all parenthetised subexpressions
as POSIX capturing groups and returns submatch according to POSIX
disambiguation rules (in variables 'yynmatch' and 'yypmatch', local
to each action).

The algorithm for disambiguation was invented by Christopher Kuklewicz.
2017-03-03 02:06:43 +00:00
Ulya Trofimovich 4fe8e273b8 Now code generation can handle zero-offset fixed tags with generic API.
We'll need this for POSIX captures: in the prsence of orbit tag,
opening tag is needed only for disambiguation; after determinization
we can pretend that it is fixed on orbit tag with zero offset.
This will save some time and space on tag optimizations and maybe
reduce the number of tag variables.
2017-03-03 01:47:03 +00:00
Ulya Trofimovich 7ec3c01eb4 Prepare default tags insertion for non-sequential tag enumeration.
This will be needed when we add POSIX captures: opening and closing
capture tags must have sequential numbers, but the tags may be located
far from each other in the regexp tree (other tags are possible on
the way from the opening tag to the closing tag).
2017-03-03 01:21:53 +00:00
Ulya Trofimovich 7f337a2451 Delay expansion of counted repetition until NFA construction time.
This is necessary to avoid creating default tags for tags that
are duplicated by expansion of counted repetition. Default tags
should only be created if zero repetitions are acceptable; this case
is still expanded early.
2017-03-03 01:15:05 +00:00
Ulya Trofimovich 225ea5362d Keep the full history of tag occurences found by epsilon-closure.
Currently this makes no difference because tag duplication in NFA
is forbidden. Anyway, we are only interested in the last occurence
of each tag on the epsilon-path to the given NFA state.

This will make difference for POSIX disambiguation strategy: we'll
have to allow tag duplication in NFA (because of counted repetition
and iteration expansion).
2017-03-03 00:56:49 +00:00
Ulya Trofimovich 515105d834 Moved splitting charset and nullable rule analysis from AST to regexp. 2017-02-26 00:05:34 +00:00
Ulya Trofimovich a27e6e232f Added yet another intermediate representation (after AST, before NFA).
Rationale: AST must be immutable, because it is shared among different
regexps, rules, conditions and blocks. NFA is mutable, but inconvenient
for some transformations (adding fixed and default tags, rewriting parts
of regexp, etc.). Before this commit all these transformations were done
in one pass (during convertion of AST to NFA) which made the code rather
complex. In order to add POSIX captures we'll need to add even more
complexity (tracking captures, creating tags for them, maintaining tag
order, etc.).
2017-02-26 00:05:34 +00:00
Ulya Trofimovich fa01aad3f7 '--dump-nfa': correctly print symbol ranges on NFA transitions. 2017-02-24 17:15:14 +00:00
Ulya Trofimovich 6cb2315828 Keep fixed and variable tags together in one array.
One must take fixed tags into account during determinization
if disambiguation policy is based on tag values.

Also, NFA construction is much easier when tags have common enumeration:
it allows to perdorm tag creation, tag fixing and adding default tags
in three distinct passes (for now they are intermixed and the code is
very complex).
2017-02-24 16:59:33 +00:00
Ulya Trofimovich cb2c243177 Stop preserving order of tag versions when mapping TDFA states.
We no longer need it; now that disambiguation policy is leftmost rather
than tag-centric, relative order of tag versions is irrelevant.
Tag versions have no impact on conflict resolution; any bijective
mapping is ok.
2017-02-14 14:51:47 +00:00
Ulya Trofimovich 5d66207284 Moved tests to subdirectory. 2017-02-14 09:53:24 +00:00
Ulya Trofimovich 919017a13d Changed disambiguation policy: leftmost rather than tag-centric.
Instead of tracking priority for each tag version and resolving conflicting
configurations encountered by the epsilon-closure based on version priorities
(trying to minimize or maximize each tag), we now simply pick the leftmost
epsilon-path through the NFA.

NFA construction has to accommodate this policy: for example, greedy iteration
should be compiled so that always choosing the left alternative correpongs to
re-iteration, while choosing the right alternative corresponds to leaving the
iteration. The necessary adjustments have been done by earlier commit
03c65121da.

Now we can drop priority comparison when mapping TDFA states and stick to
simple bijection. This may add cycles in reordering commands. (Has not been
done yet.)

The rationale of switching to leftmost policy is this: with tag maximization/
minimization policy tags could influence the regexp: for example, regexp
    "a"* @p "a"*
has different meaning depending on whether tag 'p' is minimized (first iteration
is non-greedy) or maximized (first iteration is greedy). Moreover, adding
another tag with the opposite policy and higher priority would change the
meaning (suppose 'q' is minimized and earlier tags have higher priority):
    "a"* @q @p "a"*
This all makes regexps somewhat fragile, since adding just one tag may change
the whole regexp (and in the presence of other tags, it may change parse
results).

But even worse, with tag-centric disambiguation simple (untagged) subexpressions
are inferior to tagged ones. This contradicts intuition and even POSIX standard,
where  a*(a*)  is the same as  (a*)(a*) . We don't keep to POSIX (and we can't
because of last-longest instead of first-longest semantics of iteration as shown
by the  (<|<a|<ab|<aba|abab|baba|b>|>)*  example), but even this somewhat
tag-centric standard respects non-captured parts of the regexp. Note that
Laurikari in his TRE library has to do special preprocessing of the regexp in
order to assign correct minimization/maximisation direction to each tag
depending on the context of the tag. His original tag-centric policy (open tag
is minimized and has higher priority than closing tag which is maximized,
nested tags have lower priority) is insufficient to accommodate POSIX.
2017-02-14 09:42:32 +00:00
Ulya Trofimovich ab269c6970 Don't trace tags in epcilon-cycles when building tagged epsilon-closure. 2017-02-13 21:03:39 +00:00
Ulya Trofimovich 03c65121da In greedy regexps first alternative must correspond to consuming path.
By convention first alternative has higher priority.
So, for example, the following must be true:
    r*     = rr* | <empty>
    r{n,m} = r{n} (r{m - n} | r{m - n - 1} | ... | r{1} | <empty>)
    r{n,}  = r{n} (rr* | <empty>)

For now we don't care about priorities: this is a preparatory step
before transition to greedy leftmost semantics for tags.
2017-02-13 15:01:12 +00:00
Ulya Trofimovich 752e1e41b7 Tags that occur earlier in regular expression must have greater priority. 2017-02-13 12:52:32 +00:00
Ulya Trofimovich ffa92537cd Added debug option '--dump-nfa'. 2017-02-13 12:37:40 +00:00
Sergei Trofimovich 4c856dd019 re2c: cleanup a few clang ++ warnings
Found those as:

    $ make CXXFLAGS="-Weverything -Werror -Wno-gnu-statement-expression -Wno-nested-anon-types"

- cleaned struct<->class declaration mismatch
- 'static' around local function
- 'RE2C_GXX_ATTRIBUTE ((noreturn))' around functions known to fail

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2017-02-12 18:23:30 +00:00
Ulya Trofimovich 0b2ca9bf14 Pack lookahead tags together with tag versions in TDFA state.
This packing is possible because we are never interested in version
of the tag if the given item has this tag in lookahead set.
2017-02-11 15:41:53 +00:00
Ulya Trofimovich 83f555f972 Use 'normal form' of version matrix to test if states are mappable.
Normal form is calculated for every new state before searching for
a mappable counterpart. All versions are renumbered to occupy consequent
numbers starting from one; version order is preserved.
2017-02-09 13:16:43 +00:00
Ulya Trofimovich b87a3683f6 Added tests that fail if mapping of TDFA states ignores version order.
These tests result in incorrect automaton unless mapping preserves
relative order of versions in TDFA states (respects version priority).
2017-02-09 13:01:26 +00:00
Ulya Trofimovich 4c73443ddb Stop supporting non-bijective mappings of TDFA states.
They are not very helpful, yet add much complexity to the mapping step.
This commit removes option '--non-bijective-mappings'.
2017-02-09 12:58:43 +00:00
Ulya Trofimovich bf3cc4c1b0 Assert that operands of 'copy' command are different. 2017-02-08 17:03:57 +00:00
Ulya Trofimovich 73cf309330 '--dump-dfa-raw': better formatting of item's tags. 2017-02-01 13:49:39 +00:00
Ulya Trofimovich 8514520dad '--dump-dfa-raw': show proper shadowed items with updated tag versions. 2017-02-01 09:47:01 +00:00
Ulya Trofimovich 5b7de347af Allocate final tag versions on the go instead of preallocating versions [1 .. N].
One cannot rely the fact that final versions are [1 .. N] anyway (they are renamed
during tag optimization), so this is not convenient as it seems.

Now versions start from 1, which looks better (more logical) on the pictures.
2017-01-31 18:53:57 +00:00
Ulya Trofimovich 5ca85b21e4 '--dump-dfa-raw': show shadowed NFA sub-states. 2017-01-31 09:52:40 +00:00
Ulya Trofimovich c6dbf271d1 Fixed yet another case of disordered tags update and cursor increment.
/* note [tag hoisting, skip hoisting and tunneling]
 *
 * Tag hoisting is simple: if all transitions have the same commands,
 * they can be hoisted out of conditional branches.
 *
 * Skip hoisting is only relevant with '--eager-skip' option.
 * Normally this option is off and skip is lazy: it happens after
 * transition to the next state, if this state is consuming.
 * However, with '--eager-skip' skip happens before transition to the next
 * state. Different transitions may disagree: some of them go to consuming
 * states, others don't. If they agree, skip can be hoisted (just like tags).
 *
 * '--eager-skip' makes tag hoisting more complicated, because now we have
 * to care about the type of automaton: lookahead TDFAs must skip after
 * writing tags, while non-lookahead TDFAs must skip before writing tags.
 * Therefore skip hoising cannot be done without tag hoisting in lookahead
 * TDFAs, and vice versa with non-lookahead TDFAs.
 * (Note that '--eager-skip' is implied by '--no-lookahead').
 *
 * Tunneling splits base states in two parts: head and body. Body has all
 * the conditional branches (transitions on symbols), while head has just
 * one unconditional jump to body.
 *
 * Normally tag hoisting should go before tunneling: hoisting may add new
 * candidates to be merged by tunneling. However, with '--eager-skip' tag
 * hoisting is interwined with skip hoisting, and the latter needs to know
 * which states are consuming. This is not possible if tunneling is still
 * to be done, because it may turn consuming states into non-consuming ones.
 * Another option is to disallow splitting states with non-hoisted skip
 * in the presence of '--eager-skip' (this way skip hoisting wouldn't need
 * to know tunneling results), but it's much worse for tunneling.
 */

Found by slyfox's fuzzer. :)
2017-01-25 17:50:45 +00:00
Ulya Trofimovich 38936b143f Don't loose 'YYBACKUPTAG' command in case of equal mapped versions.
Found by slyfox's fuzzer. :)
2017-01-25 13:19:53 +00:00
jcfp dd5a0077b2 correct some minor manpage typos
these showed up in lintian during a maintenance update of the debian re2c package
2017-01-23 21:19:09 +00:00
Ulya Trofimovich 65780565a0 Update tags after reading character in TDFAs without lookahead.
Fixed forgotten special case when tags and cursor increment
are hoisted out of conditional branches.

Found by slyfox's fuzzer. :)
2017-01-23 21:02:24 +00:00
Ulya Trofimovich 5446f3afd6 Fixed memory leak.
Found by valgrind:

 1,177 bytes in 1 blocks are definitely lost in loss record 1 of 1
    at 0x4C2AE40: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    by 0x42153F: re2c::cfg_t::compact(re2c::cfg_t const&, int*) (compact.cc:12)
    by 0x422088: re2c::optimize_tags(re2c::dfa_t&) (optimize.cc:18)
    by 0x42DE3A: re2c::compile(re2c::spec_t const&, re2c::Output&) (compile.cc:82)
    by 0x446742: re2c::parse(re2c::Scanner&, re2c::Output&) (parser.ypp:484)
    by 0x402DC0: main (main.cc:38)
2017-01-23 18:09:05 +00:00
Ulya Trofimovich 8e3af0511a Iterate CFG nodes in postorder to speed up liveness analysis.
Deep-first search postorder is the best possible order for solving
control-flow equations for liveness analysis.
2017-01-23 18:01:49 +00:00
Ulya Trofimovich 31a8afdf15 Use the same tag version for all transitions from the given state.
This reduces the overall number of versions greatly, which is crucial
for the space and time efficiency of tag liveness analysis.

Of course, bottom and normal transitions still have different versions.

Differents tags on the same transition also have different versions.
It is not incorrect to give them the same version: all tags updated by
one and the same transition are either set to bottom, or to current
input position (which is the same for all tags on the given transition).
But this would create many states with a very special "shape" that do
not map to other states. In fact, this would cause exponential blowup
in the number of states (even in simple cases).
2017-01-23 17:42:37 +00:00
Ulya Trofimovich 322fbb30eb Compact tag versions before doing liveness analysis.
After TDFA construction tag versions occupy non-contiguous range
of natural numbers: there may be "holes" between versions. This wastes
space (and time) spent on liveness analysis and subsequent optimization
passes. This commit adds a simple pass that renumbers versions so that
they occupy contiguios range.
2017-01-23 16:38:04 +00:00
Ulya Trofimovich 0c9681ee60 Updated parser for bison-3.0.4. 2017-01-23 16:19:24 +00:00
Ulya Trofimovich 7d362320ee Added option '--no-lookahead'.
This option makes re2c generate TDFA that does not exploit lookahead
symbol when making tagged transitions.
2017-01-18 21:01:47 +00:00
Ulya Trofimovich d2cd8821bd Added option '--eager-skip'.
This option allows to control program points in which cursor is
advanced to the next input character. Normally it happens after moving
to the next state (lazyly). With '--eager-skip' cursor is advanced
before moving to the next state (eagerly).

Eager mode presents some difficulties compared to the lazy mode:
transitions may disagree on whether advance cursor or not. Some of
them may go to accepting states and should not advance cursor, while
others go normal states and should advance cursor. In such cases
advancement must happen on a per-transition basis. If all transitions
agree on the matter, advancement can be hoisted out and performed on
a per-state basis, just as it happens in lazy mode.
2017-01-17 12:36:43 +00:00
Ulya Trofimovich 54e14cedea Reuse mode: always reparse rules and restore options of the rules block. 2017-01-15 22:38:20 +00:00
Ulya Trofimovich aa4aa2e673 Consistently use current block's options for code generation. 2017-01-01 18:47:06 +00:00
Ulya Trofimovich 2d73eb3c3a Fold output expressions in a separate pass over the output.
re2c folds sequences of simple statements to complex tatements, e.g.:
    ++YYCURSOR;
    yych = *YYCURSOR;
is folded to:
    yych = *++YYCURSOR;

It is hard to fold expressions on the fly (at the time they are generated),
because one needs to forsee all the cases in advance. Some cases cannot be
anticipated (e.g. if substatements belong to different states, which is often
the case), so many statements remain unfolded.

This commit separates code generation and folding by delaying output of
skip, peek and backup primitives. Folding now is done in a separate pass
when all the substatements are already known.
2016-12-30 17:15:16 +00:00
Ulya Trofimovich a698ea6145 Memorize options for each block and use them for delayed code generation.
Option scope is very poorly defined in re2c. Most options should have block
scope, but some have global scope (because they belong to global directives
like '/*!types:re2c ... */', '/*!tags:re2c ... */' or other global things
like generation date, etc.).

For now, options are applied immediately as they are parsed.
Code generation just reads the most recent state of options, so the output
depends not only on the location in source code when the option is defined,
but also on program points in which re2c generates and outputs code.
Generation and output may happen at different times, so they may use
different options. This is all very bad.

This commit is the first attempt to introduce scoped options: re2c now
makes a snapshot of options at the end of each block and uses this snapshot
for delayed code generation for this block (unless the given option must be
global).

This is not perfect (immediate code generation still uses 'seen-so-far'
options instead of block options), but at least it allows to delay code
generation for non-global things without loosing options.
2016-12-29 17:07:52 +00:00
Ulya Trofimovich b79ab68097 Delay code generation for condition dispatch. 2016-12-27 21:04:09 +00:00
Ulya Trofimovich 455a6e0035 Finally separated parsing, consistensy checking and after-parse transformation.
Updates in test results are caused by the changed order of condition
compilation, see commit b7bbbf471778b487d0717c85a5e586b595e495ec.
Changes do not affect code generation, only the error messages.
2016-12-27 17:09:21 +00:00
Ulya Trofimovich 7d26632d2e Emit conditions ordered by their number rather than lexicograhically.
Each condition has a unique name and unique number. Numbers are assigned
to conditions in the order they appear in source file. This order must
be preserved since some users rely on it (user code makes implicit
assumptions about condition order, see '-Wcondition-order').

However, once the order is preserved, the automata code can be emitted
in any order (user code can only address conditions by their start label,
and it can be anywhere in the output file).

This commit changes the order of automata: now they are emitted according
to their numbers, not names.

Test results have changed in cases when lexicographical order does not
coinside with number order. The changes touch some important files and
are not easy to verify. However, rearranging conditions in the generated
code back in lexicographical order makes the differences trivial (labels,
'YYDEBUG' parameter, 'YYFILL' labels, 'YYSETSTATE' parameter --- in other
words, everything that depends on state numbering). It is easy to see
that the structure of the code is not changed.
2016-12-25 18:13:43 +00:00
Ulya Trofimovich 2612c36499 Reuse 'Code' data struct for setup code. 2016-12-24 12:00:59 +00:00
Ulya Trofimovich 853b58a137 Reduced one argument to function as it is a part of another argument. 2016-12-24 11:20:48 +00:00
Ulya Trofimovich 4f7dea3a0c Parser: started gathering all error messages in one place. 2016-12-24 10:40:08 +00:00
Ulya Trofimovich 4e932493f4 Keep startup code '<>' separately from other rules. 2016-12-23 16:53:31 +00:00
Ulya Trofimovich a3a9ad672c Keep '*' rules separately from other rules. 2016-12-23 16:10:50 +00:00
Ulya Trofimovich a573940f4f Setup code for rules belongs in DFA scope, not the entire block scope. 2016-12-23 15:55:01 +00:00
Ulya Trofimovich 472cecc143 Restructured parser grammar to explicitly list different rule types. 2016-12-23 15:01:28 +00:00
Ulya Trofimovich cd04f184fb Parser grammar: separate production for code in conditional rules. 2016-12-22 22:11:08 +00:00
Ulya Trofimovich 5d2beb3111 Pass context as parameter to 'yyparse' instead of a bunch of static variables.
As a side effect of this commit a long-standing bug with setup rules
has been fixed: re2c forgot to clean up the list of setup rules together
with other data, which resulted in false errors about duplicate setup code.
2016-12-22 17:38:38 +00:00
Ulya Trofimovich 8db9150975 Removed unused typedef. 2016-12-22 16:56:15 +00:00
Ulya Trofimovich 141ddd09e8 Fixed memleaks (found by valgrind). 2016-12-22 16:53:41 +00:00
Ulya Trofimovich cbbfa5e406 Handle all types of rules in one place (in parser). 2016-12-22 14:40:32 +00:00
Ulya Trofimovich 54e910feb6 Simplified handling of user-defined code in parser. 2016-12-22 13:58:05 +00:00
Ulya Trofimovich 85b33e9f79 Inlined small function with only one user. 2016-12-22 12:04:59 +00:00
Ulya Trofimovich 5168003cf2 Simplified line tracking in lexer. 2016-12-22 11:58:48 +00:00
Ulya Trofimovich f7034511a8 Separated compilation pass from code generation pass.
They might be totally disconnected in case of '-r' option and it's
more convenient to handle them separately.
2016-12-22 09:54:13 +00:00
Ulya Trofimovich f1ffda133a Parse rules in a uniform way regardless of the '-c' option. 2016-12-21 23:14:17 +00:00
Ulya Trofimovich 2b36c4b46f Simplified parsing of startup code '<>'. 2016-12-21 22:31:34 +00:00
Ulya Trofimovich f5435dd04e Don't use special token type for '<!' and '<>'.
Parse them as character sequences.
2016-12-21 18:44:02 +00:00
Ulya Trofimovich b86f9161cc Further simplified default rule parsing. 2016-12-21 17:21:31 +00:00
Ulya Trofimovich 0928ea5225 Simplified handling of default rule in parser. 2016-12-21 17:12:09 +00:00
Ulya Trofimovich a15d55a8ab Don't loose condition if it consists of default rule only. 2016-12-21 11:43:22 +00:00
Ulya Trofimovich 2f11989800 Simplified '*' condition handling in parser. 2016-12-20 22:45:23 +00:00
Ulya Trofimovich bb6f4ff1af Moved variable from global scope to function scope. 2016-12-20 09:39:52 +00:00
Ulya Trofimovich 94a5e6df57 Make 'Scanner' parameter to 'yyparse' instead of global variable. 2016-12-19 09:59:15 +00:00
Ulya Trofimovich e558d9bae3 Removed empty header 'globals.h' and all includes of it. 2016-12-19 08:45:46 +00:00
Ulya Trofimovich 45df7b5c7e Removed variable from global scope. 2016-12-19 08:42:14 +00:00
Ulya Trofimovich de4838e79b Removed variable from global scope. 2016-12-19 08:37:46 +00:00
Ulya Trofimovich b014f14788 Removed variable from global scope, simplified bitmaps. 2016-12-19 00:06:19 +00:00
Ulya Trofimovich 3090407387 Removed variable from global scope. 2016-12-18 17:06:42 +00:00
Ulya Trofimovich 6156eb99bc Removed variable from global scope. 2016-12-18 14:56:10 +00:00
Ulya Trofimovich c9542e0863 Removed warnings from global scope. 2016-12-18 12:27:19 +00:00
Ulya Trofimovich 874bdcb1d4 Removed options from global scope. 2016-12-18 12:02:05 +00:00
Ulya Trofimovich 4266694437 Simplified code generation for initial state. 2016-12-14 16:25:54 +00:00
Ulya Trofimovich 7664ab2d69 Simplified generation of code for buffer refilling. 2016-12-14 15:16:01 +00:00
Ulya Trofimovich eb16c9a2d3 Don't delay reading next character until dispatch.
Instead of sometimes generating code like this:

    ++YYCURSOR;
    switch ((yych = *YYCURSOR)) {

re2c now always generates

    yych = *++YYCURSOR;
    switch (yych) {

There's not much difference: it's hard to say which would be better
optimized by C/C++ compiler. Most likely they would be optimized
equally well; practical experiments with GCC -O2 resulted in bit-to-bit
identical binaries.

However, dropping the first form allows to cut off a lot of tricky code
in re2c itself (a whole layer of code spread across multiple files was
tracking whether next input character has been already read or not).

Changes to the test results are multiple, but trivial; they have been
verified with skeleton.
2016-12-14 14:21:28 +00:00
Ulya Trofimovich 487225a906 Don't peek next input character if all transitions go to final state.
A similar heuristic already existed, but it was imprecise and captured
only those cases when final state happened to be next to the one in
question.

A lot of tests were updated; however changes are trivial and I verified
them with skeleton.
2016-12-14 13:35:21 +00:00
Ulya Trofimovich a4f7e2683f Renamed option '--dfa-mapping <bijective | injective>' to '--non-bijective-mapping'. 2016-12-12 13:44:00 +00:00
Ulya Trofimovich d5fa75187c Search for the best candidate in case of non-bijective mapping.
For bijective mappings there is always at most one mapping candidate,
for non-bijective mappings there may be many candidates.
2016-12-12 13:16:56 +00:00
Ulya Trofimovich 790e1acdbc Respect injective mappings when optimizing save(X), copy(Y,X) to save(Y).
If mapping is injective, there may be multiple copy commands per one
save command: save(X), copy(Y,X), copy(Z,X). In this case save command
must be replicated for each copy command: save(Y), save(Z).
2016-12-09 12:15:56 +00:00
Ulya Trofimovich a2811748af Now checking for tag priority violation respects injective mappings. 2016-12-08 17:34:12 +00:00
Ulya Trofimovich 7c5b4fd70c Fixed atrocious typo that unconditionally enabled injective mapping.
However, injectivity never showed up because every injective mapping
(as of now) is erroneously considered to violate tag priority.
2016-12-08 17:15:31 +00:00
Ulya Trofimovich 01c7f228fe Added test: exponential blowup if bottom is treated as special version.
One tempting way to track default value of tags is to forbid mapping
bottom (default) to non-bottom versions. This way we don't need to
explicitely save bottom to variable; bottom value is encoded in state
(once a tag becomes bottom, it will never become non-bottom again).

However, this may exponentially blow up the number of states.
2016-12-07 17:09:14 +00:00
Ulya Trofimovich 57392a48ef Cleaned up determinization.
Moved creation of new DFA states and finalizers to a separate routine,
together with building tag commands.
2016-12-07 15:08:58 +00:00
Ulya Trofimovich 314eb5c705 Untwined determinization and '-Wnondeterministic-tags' analysis.
Now '-Wnondeterministic-tags' analysis is done right after determinization,
while we still have all the kernels available. Instead of comparing
transition tags (which are available in closure items, but not in kernels)
we now compare tag versions: maximum number of distinct versions per tag is
the desired degree of nondeterminism. Kernel items that belong to another
rule do not count (all tags that don't belong to a particular rule should
have initial versions in all items belonging to this rule).

Added test with an example of pathological regexp: counted repetition
cannot be folded efficiently in DFA, and combined with nondeterministic
tags it results in arbitrary long chains of reordering commands.
Length of command choin grows linearly with the number of repetitions
(as DFA itself does).
2016-12-06 13:35:07 +00:00
Ulya Trofimovich 064520e0f2 Debug '--dump-adfa' option: drop 'YYFILL' in move states, it's fictive. 2016-12-05 22:19:37 +00:00
Ulya Trofimovich 6b2fe2895b Added debug option '--dump-dfa-raw'.
It dumps DFA at the very early stage of construction, expanding underlying
state kernels with NFA substates and correspondings sets of tag versions.
2016-12-05 17:32:41 +00:00
Ulya Trofimovich 8dbb6adaf5 Added option '--dfa-mapping <bijective | injective>'.
This option controls how tag versions in DFA states are mapped to each
other during determinization. By default mapping is 'bijective', however
if it is set to 'injective' the new state must be less versatile than
the old one.
2016-12-04 15:00:52 +00:00
Ulya Trofimovich f929c0c16c Debug '--dump-adfa' option: correctly display range lower bound. 2016-12-04 12:16:19 +00:00
Ulya Trofimovich 0b4c6b8a1c Drop hoisted tags in 'base' states duplicated by tunneling.
Tunneling optimization finds certain states and splits them into
two parts: First part consumes a character and unconditionally moves
to the second part. Second part does not consume characters, but
contains a switch on character value.

Second part is a 'base switch', which may be utilized by many other
states. So if the first part has hoisted tags, they should be dropped
in the second part (the aforementioned many other states may have hoisted
tags of there own or no hoisted tags at all).

Found by slyfox's fuzzer. :)

Yet unable to construct a test case that reveals the error: the original
test case found by fuzzer is not breaking anymore after recent commit
44045203c2 "Properly remove useless final states.".
2016-12-04 12:00:31 +00:00
Ulya Trofimovich 1e2e16a0c5 Fixed 'uniq' on commands (algorithm that removes duplicates).
The previous version erroneously skipped a coomand after removal,
so it would fail in case of three identical commands in a row.
2016-12-03 10:28:39 +00:00
Ulya Trofimovich d07bc5ce04 Don't loose liveness of tags that occur on both sides of 'copy' commands.
When processing chain of 'copy' commands like 'x = y; y = z;'
one should first mark all left hand sides ('x' and 'y') as dead,
then mark all right hand sides as alive ('y' and 'z'). This way
'y' will end up alive, as it should be.

Found by slyfox's fuzzer. :)
2016-12-02 23:33:51 +00:00
Ulya Trofimovich 44045203c2 Properly remove useless final states.
Before this commit the algorithm considered final state useless only
if its rule is unreachable in this state. However, this leaves out
cases when final state is shadowed by other final states of the same
rule (longer alternatives of the same rule always match). In such
cases the rule is reachable because some (maybe all) outgoing accepting
paths match the same rule.

Now the algorithm considers final state useless if all outgoing paths
are accepting (there's no default transitions and default rule is
unreachable in all successors).
2016-12-02 19:22:41 +00:00
Ulya Trofimovich 1a17032417 Retry tunnel optimization if the first attempt is unsuccessful.
This is probably a decades-old typo (misplaced 'break' statement).
Surely the author intended to try all successors, not just the first one.
2016-12-02 13:37:59 +00:00
Ulya Trofimovich a58b4eeb59 Added debug option '--dump-adfa'. 2016-12-01 16:31:56 +00:00
Ulya Trofimovich 7edbbca5a8 Topologically sort 'copy' commands.
The order in which copy commands are executed is important:
'x = y; y = z;' is not the same as 'y = z; x = y;' (the latter
overwrites 'y' before its precious value is copied to 'x').
To avoid overwrites, commands should be topologically sorted.
This is always possible because there's no cyclic dependencies
by construction.

Found by slyfox's fuzzer. :)
2016-11-30 23:02:25 +00:00
Ulya Trofimovich 67ebe3f478 Added debug options '--dump-dfa-det', '--dump-dfa-tagopt' and '--dump-dfa-min'. 2016-11-30 18:48:12 +00:00
Ulya Trofimovich 5b98063be4 Skeleton: apply 'copy' commands before 'save' commands.
This is how the generated TDFA does and how it should be done.

Found by slyfox's fuzzer. :)
2016-11-30 12:37:38 +00:00
Ulya Trofimovich 559b897428 Allow nondeterministic tags.
This commit makes some important changes:

    - Each DFA state under construction keeps a set of tag versions
      (which version of each tag is actual for each NFA sub-state).

    - Tag versions now have priorities which allow to disambuguate
      between two competing configurations when building tagged epsilon-
      closure. We try to maximaze value of each tag, thus versions
      that correspond to greater tag value have greater priority.

    - Comparison of DFA states (when trying to find an existing state
      equal to the new one) has become more complex. We try to find
      a similar enough (not necessarily identical) state: one that is
      equal to the new state up to reordering of tag versions. Mapping
      should be either bijective or injective (new state must be less
      or equally versatile then the old one), default is bijective.
      Mapping should not violate tag priorities: relative order of
      versions must hold (absolute values of priorities don't have to
      coincide).

    - On each update tag gets new version: if tag is updated to bottom,
      it gets negative version; otherwise it gets positive version.

    - Different tags that updated by the same transition still get
      different versions. This may seem to be a waste: we know exactly
      that input position is equal for all tags on the same transition,
      even more, for all tags on all outgoung transitions from the same
      state, so we can alocate exactly one version for all of them.
      However, allocating one version for different tags creates states
      with a very specific tag configurations: these states don't map
      to existing states and the automaton gets bloated (sometimes
      exponentially). Furthermore, allocating independent versions is
      good for optimizations.

    - Second pass of optimizations: it only makes difference for one
      test case (usually the first pass does a good job), but it's cheap
      (all the necessary infrastructure is in place) and powerful.

    - The resulting automaton is similar to Laurikari's TDFA, except
      for one important difference: re2c's automaton makes use of
      lookahead tags, while Laurikari's does not.
2016-11-30 11:21:27 +00:00
Ulya Trofimovich c4d95e30ef Added test: tags in trailing context. 2016-11-28 15:48:09 +00:00
Ulya Trofimovich 9c3c158e83 Keep fixed and variable tags separately.
This commit reverts commit de3f9e70a4:
    Keep fixed and variable tags together in one array.
Optimizations of variable tags get more complicated and fixed tags
should not get in the way.

This commit also drops check for tags in trailing context: there's
nothing special about them; no technical reason to forbid them.
2016-11-28 15:39:06 +00:00
Ulya Trofimovich 16d8045faa Merged computation of fixed / variable tags into NFA construction.
NFA construction is already complex because of insertion of default tags,
now it gets even worse. However, keeping two separate passes requires
maintaining exactly the same order of traversal, which is fragile.
2016-11-26 20:16:11 +00:00
Ulya Trofimovich 762a84428a Removed redundant computation.
Tags used in the given sub-regexp are already tracked by tag index;
boolean array is redundant.
2016-11-26 18:15:47 +00:00
Ulya Trofimovich d165004d92 Use different datatypes for closures and kernels.
This is a preliminary step for tracking tag versions in closures / kernels.

For now closures and kernels store the same information, but it will
diverge when we start tracking tag versions: closure items will need
some extra-data that is needed during closure construction, but shouldn't
be in kernel.

Kernel representation should also allow efficient comparison for identitiy
or compatibility (for mapping).
2016-11-26 18:02:44 +00:00
Ulya Trofimovich 9e63260ceb Skeleton: fixed comparison of transition tags during construction.
At the time of skeleton construction DFA has just been build and
all tags in it are just raw pointers to lists of commands. These
pointers are unique for each transition (tags are not shared between
transitions). This means, comparing tags for different transitions
will always result in 'not equal', except if both transitions have
no tags (pointers are NULLs).

Found by slyfox's fuzzer. ;)
2016-11-18 16:37:40 +00:00
Ulya Trofimovich 2db0433b08 Skeleton: generate proper keys for tags.
Instead of calculating all necessary keys, then attributing keys
of the first path to all paths, write proper keys for each path.

Found by slyfox's fuzzer. :)
2016-11-18 16:29:09 +00:00
Ulya Trofimovich 10b51aaee1 Track uninitialized tags and set them to default value.
Uninitialized tags come from alternative and iteration:
    ... @t ... | ...
    (... @t ...)*

Tags under alternative preserve their initial value (given to them
before entering DFA) -- they don't have to be explicitely set to
default value (but it is convenient, otherwise we'd have to initialize
all tags every time before entering DFA).

Tags enclosed in iteration might be assigned positional values on
some iterarions, but not on the last one -- their default value must
be restored explicitely before each iteration.

This commit adds specail kind of 'save' commands that set the given
tag to default value (instead of current input position). We insert
these 'save default' commands for tags in alternatives: all tags that
are present on left alternative get default values at the end of right
alternative.

Later on (during DFA construction and optimizations) we treat default
value just like normal positional value: save it to a variable, copy
values between variables, etc. This way DFA gets additional commands,
but the number of states does not grow much.

Another way would be to treat default value as a special bottom value:
instead of saving it to variable, keep a dedicated bottom tag version
and forbid mixing bottom version with other versions. This way default
values would be encoded in the structure of DFA, so there would be no
need to explicitely save them. DFA would gain no additional default
commands, but new states would appear.

Test changes have been verified with '--skeleton'.
Test 'tags/interference.i--tags.re' have been completely rewritten --
the old version no longer captures what it should (see comment in the
test). The old vesion has been moved to 'tags/fallback6.i--tags.re'.
2016-11-18 16:23:04 +00:00
Ulya Trofimovich 2ad801e636 Don't loose 'yyaccept' when fallback and initial states coincide.
Before code generation each DFA state is assigned a specific action.
Actions are mutually exclussive except for one: inital state may
coincide with fallback state. The bug was in overriding fallback
action with initial action (we lost 'yyaccept' which cause the wrong
match).

The bug was found with '--skeleton'.
2016-11-15 17:09:53 +00:00
Ulya Trofimovich 1188662b4e Reduce all final versions of the given tag to one common version.
Tag may have different final versions in different accepting states
(currently either fallback version of the main version). Now we
reduce all final versions to one (this takes one additional 'copy'
command for normal tags and none for tags that have fallback copy).
2016-11-14 17:19:26 +00:00
Ulya Trofimovich b3c4a43a64 Skeleton tests: count re2c crashes as fatal (not expected) errors. 2016-11-12 22:00:44 +00:00
Ulya Trofimovich cd9651aa70 Skeleton: code cleanup: split large function into subroutines. 2016-11-12 21:33:13 +00:00
Ulya Trofimovich 1a028ffaed Skeleton: check tags.
Calculate final tag values during string generation and put them into
'.keys' file together with the length of the consumed / matched input
and the matching rule number. Each pack of keys only gets those tags
that belong to the matching rule (no tags for default paths or paths
corresponding to untagged rules). Tags do not include trailing context,
as it is already included into the length of matching input.
2016-11-12 15:24:57 +00:00
Paulo Custodio 0def065a86 Fix #163
The previous fix to #163 (a51c7c8) was not working properly, simplified and fixed.
2016-11-11 22:11:28 +00:00
Ulya Trofimovich a51c7c858c Convert all line endings to LF before writing the generated code to file.
This commit should fix bug #163 reported by pauloscustodio:
    Reading files with "rb" causes issues in Windows

re2c reads input files in binary mode and writes the generated output in
text mode. This caused CR LF conversion to CR CR LF on Windows: first CR
comes from reading input in binary mode, second CR is added when writing
output in text mode. This only happened to those parts of input which are
not transformed by re2c: we used to copy-paste verbatim, now we patch line
endings.
2016-11-11 13:54:33 +00:00
Ulya Trofimovich c2fc2a9d51 Emulate tag calculation when generating paths for skeleton. 2016-11-10 15:44:02 +00:00
Ulya Trofimovich c560d865ef Limited skeleton lifespan to the time of DFA construction.
There's no need to pull the whole skeleton up to code generation phase:
skeleton itself is used only for string generation and tracing undefined
control flow, both things are done after DFA construction and before any
optimizations.

By the time code generation starts skeleton is obsolete: its structure
is no longer in sync with DFA and it shouldn't be used.
Code generation only needs some attributes (key size and default rule
index), which can be explicitely stored in DFA.
2016-11-10 11:24:35 +00:00
Ulya Trofimovich c57b8d21bf Moved '-Wundefined-control-flow' analysis to the point of skeleton generation. 2016-11-09 23:05:00 +00:00
Ulya Trofimovich 0e40784ec9 Skeleton: share data with DFA, generate strings before optimizing DFA.
Skeleton must use unoptimized DFA right after determinization, otherwise
it won't be able to track optimization errors. Therefore skeleton must
either use a copy of DFA, or use the original before any optimizations.
Copy-pasting the whole DFA is a waste (especially when it comes to tag
commands, which are stored in linked lists), so we take the second approach.

However, this means that skeleton '.input' files are generated every time
DFA is constructed, not every time DFA is used for code generation.
This explains changes in tests: in reuse mode, we sometimes construct
DFA and never use it for code generation.
2016-11-09 22:21:13 +00:00
Ulya Trofimovich 54b50c0bbf Recognize newlines in character strings and classes.
As for now, newline inside of a character string or class is an error:
re2c should emit clear error message. Different styles of newlines
should be recognized ("\n", "\r\n").

This commit fixes bug #162 reported by pauloscustodio:
    Reading files with "rb" causes issues in Windows
2016-11-07 09:53:57 +00:00
Ulya Trofimovich 4b07427011 Skeleton: don't keep expanded range representation in nodes.
For the most part character range is represented as a pair of bounds.
When generating data for skeleton programs we need to pick some
256 distinct characters from each range; only these characters will
participate in data generation.

Before this commit range expansion happened at the time of skeleton
construction. Now it is delayed until the time of dumping skeleton
paths to file. This means that expansion of particular range is done
multiple times (every time the corresponding skeleton multiarc is
dumped to file). However, data generation only happens with '--skeleton'
option, while skeleton construction is unavoidable.
2016-11-06 15:11:31 +00:00
Paulo Custodio 042696f7e8 Open text files with "wb" causes issues on Windows
Text files need to be opened for writing with "w", so that stdio does
the right thing in respect to the correct line endings for the current OS.
("\r\n" in Windows, "\n" in Linux).
2016-11-05 16:01:36 +00:00
Ulya Trofimovich 334c650bd3 run_tests.sh: patch line endings in the generated file.
Line endings in the generated code depend on the target platform: e.g.,
"\r\n" on Windows vs. "\n" on Linux. However, reference test results are
(currently) generated on Linux and therefore contain "\n" line endings.
So we have to patch line endings in the generated code in order to pass
the tests on Windows.

Testing script did patch line endings in stdout and stderr, but forgot
to patch them in the generated file (it was broken since we started to
use '-o' option for testing). This commit fixes testing script.

It also deletes a couple of tests in which source code contains "\r\n"
instead of "\n". These tests are duplicates of other tests (they were
added by commit bd2875441c supposedly to
test that re2c preserves line endings in source code). They are broken
by current commit and fixing them is probably not worth of the effort.
2016-11-05 15:24:02 +00:00
Paulo Custodio 0f644ae635 Inconsistent forward declaration of struct/class vs definition
structs State and OutputFile forward declared as class.
classes Range, RegExp and RuleOp forward declared as struct.

Fixed forward declarations.
2016-11-05 00:30:32 +00:00
Ulya Trofimovich cdaad4b150 Added test and comment about tag backups in fallback states. 2016-11-04 15:01:47 +00:00
Paulo Custodio c428429402 Fix #156
Rename INFINITY to INFINITE so that it does not clash with infinity from
the MS C++ library.
2016-11-03 08:35:57 +00:00
Ulya Trofimovich 318570f543 Moved tag optimizing functions to 'cfg_t' struct namespace. 2016-11-02 18:30:47 +00:00
Ulya Trofimovich 73083d9ece Moved tag optimization stuff to subdirectory. 2016-11-02 17:53:33 +00:00
Ulya Trofimovich 5f85007025 Slab allocator for tag commands. 2016-11-02 17:20:27 +00:00
Ulya Trofimovich ca7db03db5 Disallow accidental change of tag commands that share representation.
After inserting commands into common index some of them may share
representations in memory. Initially commands are stored in mutable
lists, which is very convenient for tag optimizations. However,
leaving this representation after indexing is dangerous, because
accidental modification of one command may affect other commands.

This commit hides mutable lists behind indices in hash table.
Table gives read-only access to the lists.

Table index is 32-bit, which is smaller than the previous 'index'
type (a pair of pointers). So in theory command comparison has
become a little faster.
2016-11-02 15:44:49 +00:00
Ulya Trofimovich 0af499f6ab Pre-calculate initial liveness of final tag versions used in rules. 2016-10-31 17:47:48 +00:00
Ulya Trofimovich 286d738a01 Restricted 'Tagpool' lifetime to DFA construction phase. 2016-10-31 16:05:16 +00:00
Ulya Trofimovich 77ad735d0f Build control flow graph of DFA before tag optimizations.
DFA may be very large, but have only few tagged transitions.
In such cases doing tag optimizations on the whole DFA is a waste:
space aloocations and (respectively) processing time is proportional
to the number of all DFA transitions.

Instead, we spend a little effort to create CFG. It has one basic
block per each tagged transition or tagged final state, plus root
basic block.
2016-10-31 14:45:45 +00:00
Ulya Trofimovich 77c3c125e8 Update struct field instead of passing return value. 2016-10-31 13:44:43 +00:00
Ulya Trofimovich 994dba7ea6 Added comment. 2016-10-27 15:34:56 +01:00
Ulya Trofimovich c34d3ce6bd Constified comparison predicate in lookup table. 2016-10-27 14:56:06 +01:00
Ulya Trofimovich db3810529c Use linked lists instead of arrays for 'save tag' commands.
Fixed-length arrays are widely used during DFA construction, where
we need to keep all versions of all tags in each NFA sub-state of the
DFA state under construction. These arrays are deduplicated, indexed
and stored in a hash table.

However, after determinization we deal with small (probably empty)
sets of tag versions that are updated on a given transition.
Corresponding arrays are sparse. We don't care about storage space
(arrays are deduplicated anyway), but traversing sparse arrays is
wasteful and the code is somewhat bloated.

We already used linked lists for 'copy' commands; now we also use
them for 'save' commands.
2016-10-27 14:29:28 +01:00
Ulya Trofimovich 6d13e22ec1 Minor tweak in tag version allocation; updated tests.
The previous commit 394fec90c1
"Use tag versions to implement fallback tags." added copy coalescing
and introduced serious changes to allocation algorithm. It simulated
the order of allocation used by previous algorithm to preserve test
results.

Now we drop this simulation and keep to the natural order: it is easy
to see that changes in test results are caused by different order of
tag version allocation.
2016-10-26 15:28:21 +01:00
Ulya Trofimovich 394fec90c1 Use tag versions to implement fallback tags.
This commit adds new data structure to represent copy commands for
tags: list of pairs (X, Y) which stand for command 'X = Y'.

Previously we used the same bit vectors that are used for constructing
DFA states, but this representation is inconvenient.

We no longer need special tag names (postfixed with underscore) for
fallback tags: we simply use a fresh version for each fallback tag.
2016-10-26 15:01:43 +01:00
Ulya Trofimovich dc7fe43739 Split tag optimization into multiple files. 2016-10-22 17:46:23 +01:00
Ulya Trofimovich f5a5b8cfe7 Introduced tag versioning.
Instead of treating tag as boolean variable (true - present,
false - absent) we now allow it to have many versions. Special
version value 'TAGVER_ZERO' denotes tag absense (corresponds to
'false').

For now, each tag has exactly one version except 'TAGVER_ZERO':
tag's number plus one.

We need tag versions because with only two values it's impossible
to expess more subtle states, e.g. initialized / uninitialized.
Tag versions will also allow to treat fallback tags like any other
tags (in particular, allow them participate in deduplication).
In future, when we add nondeterministic tags, versions will be used
to implement tag copies.
2016-10-22 13:19:13 +01:00
Ulya Trofimovich 262c22617c Moved tag liveness data out of Tagpool.
This is necessary to introduce tag versions: we'll have to
calculate liveness of tag versions (rather than tags) and won't be
able to keep liveness data in Tagpool.
2016-10-19 13:33:23 +01:00
Ulya Trofimovich efb9b505b2 Tag liveness: use control-flow analysis instead of backward propagation.
This commit effectively reverts commit eeceb1d5ba,
"Use backwards propagation for liveness analyses on tags.", which changed
control flow analyses to backward propagation of liveness from final states.

The reason for rollback is that common control-flow analysis is more
general. Backward propagation is simple if tags are only used in final states.
While this is currently true, but we'll have to allow tag uses on arbitrary
arcs, and this will complicate backward propagation a lot.
2016-10-17 18:22:34 +01:00
Ulya Trofimovich 5cee3d715f Make tags absolute, not relative.
Relative tags have some advantages:
    - only base marker has to be updated by YYFILL
    - ever-broken old code with overlapping trailing contexts
      can be fixed without user's help (provided that re2c
      autogenerates declarations of tag variables)
    - fixed-length contexts may be used with generic API
      (though it becomes less generic with relative tags,
      as we rely on the concept of relative offset)

However, the generated code is less efficient in simple cases
(default API, no YYFILL): relativity adds extra arithmetics with base
marker (which implies dereference of base marker in most of the cases),
so the code is actually worse than hand-written.

Even with YYFILL it turns out to be more efficient to keep all tags
in a struct together with other pointers and update them once in a
while: YYFILL is called very infrequently (if properly implemented
by the user), while tag operations happen unconditionally.

However, making tags absolute means that re2c will fail with error
on old code with overlapping trailing contexts (unless they have fixed
length or can be deduplicated). These cases are probably rare.

Generic API can't make use of fixed tags, but becomes truly generic:
'YYBACKUPTAG / YYRESTORETAG / YYCOPYTAG' make less assumptions
about the input.
2016-10-11 14:14:26 +01:00
Ulya Trofimovich c9168a351b Don't generate 'yyt<N>' variables without explicit '/*!tags:re2c*/'.
Reasoning:
    - with YYFILL, one must use '/*!tags:re2c*/
    - without YYFIL, one might still want to use '/*!tags:re2c*/'
      (e.g. to avoid warnings about initialized variables)
    - unconditional behaviour is easier to remember
    - everyone who uses tags should know about '/*!tags:re2c*/'
    - re2c code is simpler

Problems:
    - without scoping rules multiple blocks with tags are troublesome

Note that actual code generation for '/*!tags:re2c*/' is still delayed.
2016-10-06 16:50:09 +01:00
Ulya Trofimovich 9cedcbce9e Renamed configurations and updated tests.
'tags:line' -> 'tags:format'
    'tags:sep' -> 'tags:separator'
2016-10-06 16:28:38 +01:00
Ulya Trofimovich c721dba117 Merged 'ir/tagpool.{h,cc}' files into 'ir/tag.{h,cc}' files. 2016-10-06 14:14:50 +01:00
Ulya Trofimovich ac292bf8ec Renamed header and added forgotten function. 2016-10-06 14:14:36 +01:00
Ulya Trofimovich a501cc8cfe Forbid fixed tags in case of generic API.
This is a preparation step before making tags absolute (rather than
relative to context marker). Generic API should make no assumptions
about the input source; in particular, it should not rely on the
notion of distance between input positions.
2016-10-06 13:44:34 +01:00
Ulya Trofimovich e6f1bbb684 Dump final tag values to variables; actions must use these variables.
Having one variable per tag name is convenient:
    - tag calculation is not duplicated if tag is used multiple
      times in the action body
    - tag name is an l-value
    - there's no need to patch actions

Variables are user-defined: users know which variables they need
(unlike distance variables 'yyt<N>', which are generated by re2c
and affected by things like tag fixedness, deduplication, etc.);
users may also want to initialize these variables in some particular
way.
2016-10-06 12:35:13 +01:00
Ulya Trofimovich 1dccc67097 Renamed configuration 'tags:expr' to 'tags:expression'. 2016-10-05 22:38:46 +01:00
Ulya Trofimovich 3aa247e1a6 Renamed default tag prefix from 'yytag' to 'yyt'. 2016-10-05 22:20:07 +01:00
Ulya Trofimovich 50386cb05a Buffer statements into a list to avoid complex pre-counting.
Formatting of 'if' or 'case' statements depends on the number of
statements in the correspoonding code block: multi-statement blockss
must be wrapped in braces or extra-tabulated.

Estimating the number of lines has never been particularly elegant,
but it gets worse every time we add possible new instructions to
transitions.
2016-10-05 21:56:58 +01:00
Ulya Trofimovich 2b7aec358e Backup overwritten tags in fallback states.
We need to backup tags in fallback states: these tags may be
updated on some non-accepting path from fallback state, and if
the attempt to match longer rule fails, there's no way to restore
the overwritten tags.

Such tags may appear in self-overlapping rules, e.g.:
    (@p "ab")* {}

We create a special backup variable for each potentially overwritten
tag. Backup tags do not participate in deduplication.
2016-10-05 17:32:56 +01:00
Ulya Trofimovich 71e94f3e4e Fixed tags comparison in table minimization.
Bug was introduced in commit 5958a2366c
"Bind contexts (a.k.a. tags) to DFA transitions, not states.":
instead of comparing tags of single transition on one particular
symbol, we compared tags for all outgoing transitions at once
(probably copy-paste from Moore minimization).

The bug was revealed by multiple tests (including '--skeleton' ones)
as soon as I ran testsute with '--dfa-determinization table'.
2016-10-04 17:05:20 +01:00
Ulya Trofimovich 8d21be9b69 More efficiently merge closure tags from different rules.
Exploit the fact that closure items are grouped by rule
instead of messing with a bit mask of rule tags.
2016-10-03 12:23:25 +01:00
Ulya Trofimovich b334de679f Attribute tag liveness to edges, not states (to refine analysis).
State granularity is too crude: there might be
two different paths to the same state, with some tag alive on one
path but not on the other. If liveness is attributed to states, then
tag liveness on one path implies tag liveness in the join state,
which affects the other path. But if liveness is attributed to
edges, then liveness of one path won't affect liveness of the other.
2016-09-30 11:22:53 +01:00
Ulya Trofimovich e11a1503f5 Liveness of fallback tags is a forward-propagagation problem.
re2c used to merge all possible fallback tags and backward-propagate
them from states that have default transitions. This is an
overapproximation; some tags are marked alive while they are not.

Liveness of fallback tags should be forward-propagated, because
this is the only way to track paths that really need these tags
(that is, paths that start in final state and end with default
transition *without passing through another final state*).

Note that sometimes we can get to the same default transition
following two different paths, one path may passing through final
state; the other is not. One path cares for fallback tags; the
other doesn't. We have no way to find out if we start bacward
prpagation of fallback tags from default transition.
2016-09-29 18:33:51 +01:00
Ulya Trofimovich aa67fff353 Comments and minor code rearrangements; nothing serious. 2016-09-28 17:07:28 +01:00
Ulya Trofimovich 3f6534df99 Tags can be calculated immediately after closure construction. 2016-09-28 15:52:11 +01:00
Ulya Trofimovich 2a6d515176 Typo in comment. 2016-09-28 14:20:08 +01:00
Ulya Trofimovich a11ca79fc7 Sort closure right after construction. 2016-09-28 14:14:55 +01:00
Ulya Trofimovich 5d4baef32f Drop shadowed final NFA states when constructing DFA state.
By construction NFA has exactly one final state per rule.
Thus closure has at most one final item per rule (in other
words, all final items in closure belong to different rules).
The rule with the highest priority shadowes all other rules.
Final items that correspond to shadowed rules are useless
and should be removed as early as possible.

If we let such items remain in closure, they may prevent the
new DFA state from being merged with other states. But this
won't affect the resulting program: meaningless finalizing tags
will be removed by dead code elimination and after that DFA
minimization will merge equivalent final states.

But it is much easier and cleaner to remove useless items
immediately (and thas't what we do).

Some '--skeleton' tests changed: this is caused by collapsed
DFA states (shadowed final NFA states prevented them from
being collapsed before). All changes are verified with '--skeleton'.
2016-09-28 14:02:28 +01:00
Ulya Trofimovich 3322f61646 Use 'Tagpool' for tag configurations during closure consruction.
Now that conflicting tag configurations are no longer merged,
we can insert them into 'Tagpool' immediately. This allows us
avoud ugly trick with 'union' in closure items.
2016-09-27 16:22:09 +01:00
Ulya Trofimovich 2ead99e4f9 Don't merge conflicting tags, choose arbitrary configuration.
Merging conflicting tags doesn't make sense: information is lost
anyway.
2016-09-27 15:48:27 +01:00
Ulya Trofimovich 5cf0a227c5 Use explicit constant 'ZERO_TAGS' instead of 0. 2016-09-27 15:11:05 +01:00
Ulya Trofimovich 5003f00ab6 Ported 'Tagpool' on 'lookup_t' and got rid of 'ord_hash_set_t'.
An effort to reduce entities with similar functionality:
'lookup_t' is more flexible than 'ord_hash_set_t'.
2016-09-27 13:43:23 +01:00
Ulya Trofimovich 0ee5609730 Removed unused header. 2016-09-27 13:21:48 +01:00
Ulya Trofimovich 756b938077 Use 'std::vector' to store closure items during determinization.
This makes code somewhat clearer compared to using plain C arrays:
all function accept one parameter (vector) instead of two (array
start, array end/array length).

However, vectors have nontrivial structure and 'ord_hash_set_t'
is not suitable for them. That's why instead of 'ord_hash_set_t'
we now use 'lookup_t': just like 'ord_hash_set_t' it has constant
random access ang logarithmic insertion complexity, but unike
'ord_hash_set_t' it is not meant to be a container (rather an index).
2016-09-27 13:00:23 +01:00
Ulya Trofimovich 101bad34f8 Restructured determinization algorithm DFA construction in a more canonical way.
All textbooks describe determinization (powerset construction)
like this:

    S0 <- epsilon-closure of start NFA state
    add S0 to DFA
    while there is unmarked state S:
        mark S
        for each symbol X in the alphabet:
            R <- the set of NFA states reachable from S on X
            T <- epsilon-closure of R
            if T is not in DFA
                add T to DFA

In re2c the inner loop on alphabet symbols was split in two parts
and somewhat obfuscated; this commit makes re2c follow textbook
version more closely.
2016-09-26 17:09:18 +01:00
Ulya Trofimovich 150c847229 Moved important DFA construction subroutines into separate files. 2016-09-26 15:35:17 +01:00
Ulya Trofimovich 30cebcbb3e Base '*' (zero or more repetitions) on '+' (one or more repetitions).
This commit effectively reverts commit 5cf441dc93
"Base '+' (one or more repetitions) on '*' (zero or more repetitions)."

It turn out, there is a good reason for using '+' as base operation:
'*' can be expressed in terms of '+' as 'r* ::= r+ | <empty>', while
'+' expands as 'r+ ::= r r*' and 'r' is duplicated.

Duplication becomes crucial in presence of tags: if the duplicated
subexpression has tags, then duplication causes an error.
2016-09-26 12:29:27 +01:00
Ulya Trofimovich 4f153f7717 Added test fot bug #152 "Line number in #line directive after enum
YYCONDTYPE is 0-based".

(thanks to sirzooro for reporting)
2016-06-28 21:44:58 +01:00
Ulya Trofimovich 691a28a17c Fixed #147 "Please add symbol name to "can't find symbol" error message".
As suggested by sirzooro:
    Please add symbol name to "can't find symbol" error message,
    it would allow to quickly spot what is wrong. Now we have to
    position cursor at given row and column to find that name.

Also tweaked error reporitng function to append "..." at the end
of the message if it didn't fit into buffer.
2016-06-25 17:09:42 +01:00
Ulya Trofimovich d1b118187b Fixed bug #145 "Values for enum YYCONDTYPE are not generated
when default rules with conditions are used".

Default rule is handled in a special (delayed) way;
re2c uses different code for default rule than for normal rules.
This special code simply forgot to add condition name to the list
of conditions.

Thanks to sirzooro for bug report.
2016-06-24 22:46:16 +01:00
Ulya Trofimovich 949596c1e7 Traverse NFA from left to right when building epsilon-closure. 2016-05-25 10:52:20 +01:00
Ulya Trofimovich b44b8b6706 Flip dimensions in 2d array (as it is slightly more convenient). 2016-05-23 23:10:50 +01:00
Ulya Trofimovich 172e8e2c53 Renaming only. 2016-05-23 22:37:10 +01:00
Ulya Trofimovich f51403dc4a Remove useless final states; calculate fallback states more accurately.
Removing useless final states allows some further optimizations
which would otherwise be impossible (see the changed tests for
example).

However, removing useless final states revealed previously hidden
defects in calculating fallback states: in some tests spurious
new 'yyaccept' values appeared. It turned out that we used incorrect
(imprecise, too pessimistic) algorithm to calculate fallback states:
the given state was considered to be fallback state if it was final
and had transitions to non-default and non-final states. This
algorithm erroneousl captures cases when all paths from the given
state are accepting and long enough (longer than one transition).
The new algorithm to find fallback states uses information obtained
by rule liveness analyses (reachability of "none-rule" in particular).

Some important tests changed a lot; skeleton says the changes are
correct (as well as manual looking into the changes).
2016-05-23 22:27:20 +01:00
Ulya Trofimovich 1478ee98f9 Fixed rule reachability analyses.
The previous algorithm handled loops incorrectly: if deep-first search
from current DFA state happened to visit looping paths before non-looping
paths, then result accumulated from non-looping paths was not propagated
into loopback states.

Now we use back propagation (from states that have transitions to default
state), which handles loops correctly.
2016-05-23 14:28:19 +01:00
Ulya Trofimovich f23886af40 Tag deduplication should go before DFA minimization.
Tags prevent minimization in some cases; deduplicating them before
minimzation gives better chances to the latter.
2016-05-19 13:04:11 +01:00
Ulya Trofimovich b47973942d Don't bother with reachability when reporting nullable rules.
We couldn't trace all unreachable nullable rules anyway, e.g.:
    [^]?
Nullable part of this rule is unreachable, but it was reported.
Besides, there's nothing bad in reporting all probles at once.
2016-05-19 11:37:11 +01:00
Ulya Trofimovich e3680da836 Give up the idea of sharing reversed DFA across different algorithms.
Reversed DFA reflects state of the original DFA in the moment when
its reversed copy was built. Original DFA undergoes many changes;
it's hard (and needless) to keep reversed DFA in sync with the
original.

We only need reversed DFA in a couple of places, better make a new
copy in each case.
2016-05-19 00:16:02 +01:00
Ulya Trofimovich 312a54ba94 There's no use in looping twice when tracing default paths. 2016-05-18 16:57:40 +01:00
Ulya Trofimovich eeceb1d5ba Use backwards propagation for liveness analyses on tags.
In commit a7a26d17ce we added fix-point
iterative algorithm to do liveness analyses on tags:

    The usual algorithm for liveness analyses doesn't use DFS;
    instead, it iterates on DFA states until fix point is reached
    (next iteration adds no changes to live set compared to the
    previous iteration). The fix applies this algorithm.

However, instead of iterating until fix point is reached, one may
use backwards propagation of live variables starting from the points
where these variables are used.
2016-05-18 15:30:49 +01:00
Ulya Trofimovich 7726029aa9 Moved loop-invariant code out of loop. 2016-05-17 18:55:03 +01:00
Ulya Trofimovich a61dee4c66 Use tagpool to store and manipulate intermediate tag sets.
Tagpool now has a special buffer to accommodate the needs of
intermediate calculations involving tag sets. Tagpool is in charge
of these calculations now; it has various functions to merge,
mask and whatever one has to do with tag sets.
2016-05-17 17:46:05 +01:00
Ulya Trofimovich a7a26d17ce Fixed bug in tag liveness analyses (tags lost in loops).
Example that revealed failure (added as test):
    (@p "ac")* "b" { @p }

We used forward propagation: starting from initial state, walk DFA
in deep-first order; in each state, add tags associated with rule
or fallback set if necessary, then recurse to child states, then
merge all child sets into this node's live set.

This algorithm cannot propagate live tags in loops in cases when
DFS visits loopbacks before non-looping paths (tags don't propagate
into loopback states).

The usual algorithm for liveness analyses doesn't use DFS;
instead, it iterates on DFA states until fix point is reached
(next iteration adds no changes to live set compared to the
previous iteration). The fix applies this algorithm.

A more efficient algorithm may be possible; one that uses backwards
propagation instead of fix point (I'm not sure).
2016-05-17 17:11:40 +01:00
Ulya Trofimovich 6857832429 Fixed occasional double-freeing tag names.
Tag names belong to regexps, which may be shared between automata,
so names should be freed on regexp destruction, not on automata
destruction.
2016-05-15 17:49:52 +01:00
Ulya Trofimovich 643f5fd795 Code cleanup. 2016-05-14 15:34:54 +01:00
Ulya Trofimovich 76b80e693b Don't forget to dereference tag aliases.
Some tags are merged to other tags during tag deduplication.
These tags are referenced by their distinct name in action code,
but in fact they are just aliases to their representative tag
(origin).
2016-05-14 14:46:39 +01:00
Ulya Trofimovich d02661df0a Moved dispatch on fixed/variable tags inside of tag-printing function. 2016-05-13 14:35:10 +01:00
Ulya Trofimovich e705710cb0 Fixed tag substitution.
If one tag name, say 'p', is a prefix of another tag name, say 'p1',
and we try to substitute all occurences of '@p' in the given string,
we might occasionally substitute '@p1'.

I made a small re2c lexer that recognizes tag-like lexemes and
tries to match them agains rule's tags. If a tag's name matches the
recognized substring, than it is the perfect match (name cannot be
a prefix of a longer name because lexer recognizes the longest match).
2016-05-13 13:51:44 +01:00
Ulya Trofimovich 259c5316c5 Code cleanup: removed useless/added missing includes. 2016-05-11 17:18:01 +01:00
Ulya Trofimovich 1224f5b8cb Don't use '-Werror-nondeterministic-tags' with '-T, --tags'.
If tags are explicitly enabled, re2c should always fail with error
on nondeterministic tags. There's no good in '-Werror-nondeterministic-tags'
diagnostic --- the user cannot reset it anyway.

This commit fixes unsuccessful attempt 2bfe75d57c
"Restore user warnings after temporarily enforcing a warning.", which
resulted in hiding tag errors if '-Wnondeterministic-tags' is not set.
2016-05-11 16:49:59 +01:00
Ulya Trofimovich 40bf6067da Fixed bug #142 "segvault with null terminated input"
Steps to reproduce:
    $ echo -ne "&\x00" > A
    $ re2c A
    Segmentation fault

Analyses: when re2c finds NULL in the input file, it checks for the
end of input; if indeed it has reached the end of input, it stops.
Otherwise, it's just some NULL byte in the middle of input; it should
be handled like any other character.

The first case (NULL as end of input) was handled correctly, but
in the second case (NULL in the middle of input) re2c crashed:
someone forgot to put an appropriate 'goto' statement, which caused
completely ad-hoc control flow in lexer.
2016-05-11 15:47:37 +01:00
Ulya Trofimovich 54711f6124 Fixed bug #142 "segvault with null terminated input"
Steps to reproduce:
    $ echo -ne "&\x00" > A
    $ re2c A
    Segmentation fault

Analyses: when re2c finds NULL in the input file, it checks for the
end of input; if indeed it has reached the end of input, it stops.
Otherwise, it's just some NULL byte in the middle of input; it should
be handled like any other character.

The first case (NULL as end of input) was handled correctly, but
in the second case (NULL in the middle of input) re2c crashed:
someone forgot to put an appropriate 'goto' statement, which caused
completely ad-hoc control flow in lexer.
2016-05-11 15:26:56 +01:00
Ulya Trofimovich 12f748758d Don't loose tags on epsilon-loops in NFA. 2016-05-11 14:48:25 +01:00
Ulya Trofimovich d726003e3b Added tests for tags (nondeterminism, unsuccessfull minimization). 2016-05-11 13:27:07 +01:00
Ulya Trofimovich 2bfe75d57c Restore user warnings after temporarily enforcing a warning.
This is a temporary (and quite inconvenient) hack; in fact,
warnings should be handled in the same way as options (via
user config / real config that are synced on each read access
just in case user config has been changed).
2016-05-11 13:17:20 +01:00
Ulya Trofimovich b9aebe51a9 Fixed memleak. 2016-05-11 11:48:01 +01:00
Ulya Trofimovich 2cac33a7d1 Allow to override output and header filenames with configurations. 2016-05-11 11:17:49 +01:00
Ulya Trofimovich 9b49cd3c4f Fixed parsing of some configurations (forgot to parse semicolon).
Added test for various 're2c🎏' configurations.
2016-05-10 16:48:29 +01:00
Ulya Trofimovich 66e62fa8cf Added tests for bug #121 "trailing contexts are fundamentally broken". 2016-05-10 15:17:51 +01:00
Ulya Trofimovich ae9dbe4ac9 Code cleanup: use anonymous union to shorten names. 2016-05-10 14:12:26 +01:00
Ulya Trofimovich df1d7a67b0 Renamed 'contexts' to 'tags' (and all related stuff likewise).
No serious changes.
2016-05-10 14:02:59 +01:00
Ulya Trofimovich de3f9e70a4 Keep fixed and variable tags together in one array.
This complicates tag deduplication a little (fixed tags have to be
masked), but simplifies tag initialization and rule handling.
2016-05-09 15:13:42 +01:00
Ulya Trofimovich 362fc83f67 Don't force mutations of immutable regexp AST.
Regexp AST should stay immutable as it may be shared between
different conditions. This means we have to store tag indices
somwhere else.
2016-05-06 11:45:04 +01:00
Ulya Trofimovich 04b37b1bbc Allow tags in any part of regexp, not only on top-level concatenation.
Fixed-length tag optimization applies only to top-level concatenation:
since we cannot predict which path lexer will choose, we cannot be
sure that any tags except top-level concatenation will ever be
initialized. If a tag may be uninitialized, we cannot fix other
tags on this one (we cannot even fix same-level tags relative to
each other, because fixed tags won't preserve the default value).
2016-05-05 17:17:06 +01:00
Ulya Trofimovich 4ba792fe7f Fixed comparison for struct 'kitem_t' (constified both operands). 2016-05-02 11:01:57 +01:00
Ulya Trofimovich 5958a2366c Bind contexts (a.k.a. tags) to DFA transitions, not states.
This is a very imortant change: it makes tracing tag conflicts as
simple as comparing tags on transitions during DFA construction.
If during determinization we get two identical transitions that
differ only in tags, then we have a tag conflict. Tags that cause
conflicts are called non-deterministic (since they don't allow
deterministic match).

This approach if very similar to Ville Laurikari's TDFA: as he does,
we first build TNFA and then apply determinization; however Laurikari's
TDFA uses complex bookkeeping to track all possible tag values,
while re2c simply forbids tags that cannot be matche efficiently.

Binding tags to transitions allows more fine-grained liveness
analyses, dead tag elimination and tag deduplication.
2016-05-02 10:40:04 +01:00
Ulya Trofimovich c1270ecf87 Keep rule number in each NFA state (not only in final states).
This is currently not necessary, but we'll need it to distinguish
between different rules when comparing tags: if rules are different,
we don't care about tag difference; otherwise tags must be equal.
2016-05-01 13:29:47 +01:00
Ulya Trofimovich ff902c2a70 Cleanup in codegen (minor changes in '-D, --emit-dot' output).
- more elegant hanling of default case when generatin code
      for 'switch' cases
    - dumbed down complex logic behind the generation of sequential
      'if' statements: explicitely list all different cases and
      corresponding conditions
2016-05-01 12:59:24 +01:00
Ulya Trofimovich 14db44c0de More precise liveness analyses for context deduplication.
Liveness analyses should exclude contexts that are updated before
they are used past certain point in the program.
2016-05-01 09:18:07 +01:00
Ulya Trofimovich 58ed3a6bda Cleanup in code generation (mostly formatting). 2016-04-30 20:07:54 +01:00
Ulya Trofimovich 6548b2e045 Simplified rule tracking during DFA construction. 2016-04-30 17:10:31 +01:00
Ulya Trofimovich a4378f9e29 Simplified collecting context names during code generation. 2016-04-30 17:04:27 +01:00
Ulya Trofimovich a5f3e7ae3a Rule contexts are consecutive, so we only need to store bounds. 2016-04-30 17:01:28 +01:00
Ulya Trofimovich e289b22747 Count contexts after deduplication. 2016-04-30 17:01:28 +01:00
Ulya Trofimovich 3057814e26 Break from loop if the remaining iterations have no effect. 2016-04-30 16:25:29 +01:00
Ulya Trofimovich 3f9fedf93f Cleaned up code that merges arcs while tunneling DFA.
Behaviour should be unchanged.
2016-04-30 16:18:54 +01:00
Ulya Trofimovich 68cfccd6a1 Fixed #141 "Tests under Windows".
Thanks to Abs62, who noted that under Windows (in MSYS) tests fail
because '2>"$outc.stderr"' dumps CRLF to file instead of LF
and proposed a fix:
    sed -i 's/\r//g' "$outc.stderr"
2016-04-29 08:16:12 +01:00
Ulya Trofimovich 8273692408 Moved conditions and contexts from global scope to block scope.
Directives like '/*!re2c:types*/' and '/*!re2c:contexts*/' have
global scope, they are not binded to any particular block and therefore
accumulate items (conditions/contexts/etc.) from the whole program.

There's currently no way to bind these directives to a particular
block (re2c will probably add scoping rules in future).

However, things like default context declaration or condition dispatch
have block scope (it's only natural that they are binded to the block
that generates them).

Unrelated change: context marker should be set for each condition,
re2c must generate it after condition label: this way code that skips
condition dispatch and jums directly to condition label will still
have context marker adjusted properly.
2016-04-05 23:01:33 +01:00
Ulya Trofimovich 6cc8a34108 Added configurations for all command-line options. 2016-04-05 12:38:53 +01:00
Ulya Trofimovich 4e0f079e41 Separated .dot code generation from common case. 2016-04-03 17:00:37 +01:00
Ulya Trofimovich f004de29a6 Omit some useless newlines in the generated code. 2016-04-03 08:31:25 +01:00
Ulya Trofimovich e67f99dbfe Lexer: minor code cleanup (check errors before doing anything else). 2016-04-02 22:06:25 +01:00
Ulya Trofimovich 877c375b0c Lexer: moved 'end of comment' sublexer to a separate function. 2016-04-02 18:52:52 +01:00
Ulya Trofimovich 7280f0ea5c Lexer: unified handling of various re2c directives.
Now when lexer encounters the beginning of a new directive, it
dumps all the intermediate code to the output.

Before this commit re2c lexer dumped intermediate code on each
newline that occured in the input.

So this commit affects two aspects:
    - Intermediate code is dumped much less often: it's good for
      performance, but it becomes more probable that the intermediate
      code will occasionally occupy too much buffer space and incur
      buffer resize.
    - Some re2c directives ignored characters right before the
      (on the same line). These unfortunate characters are no longer
      ignored.
2016-04-02 17:25:23 +01:00
Ulya Trofimovich 96278bffee Lexer: drop useless rule.
The 'end of comment' rule was used to detect end of re2c directives;
however, now it is handled by a special 'end of comment' lexer block.
2016-04-02 15:21:50 +01:00
Ulya Trofimovich 0ba58e2afd Lexer: don't care if end of comment is followed by a newline.
re2c used to swallow newline that immediately followes end of directive:
for most of the directives re2c generates code block that ends with a
newline, so the generated code looks better if the newline is not doubled.

However, this unnecessarily complicates the lexer.
2016-04-02 15:07:59 +01:00
Ulya Trofimovich ef3536b491 Lexer: suppressed directives in skeleton mode, cleaned up code. 2016-04-02 11:41:04 +01:00
Ulya Trofimovich d2378f6c36 Explicitely handle empty string in lexer.
(rather that hide it inside of a definition)
2016-04-01 21:37:03 +01:00
Ulya Trofimovich a90c1c4960 Added directive '/*!contexts:re2c ... */'.
Directive is a new type of re2c block that consists of zero or more
of the following configurations (example values are the defaults):
    line = "long @@;";
    sep = "";

Renamed configuration: 're2c:ctxprefix' -> 're2c:contexts:prefix'

Added configuration: 're2c:contexts:expr = "@@"' that allows to
override the way context markers are accessed (but nottheir names).

Removed configuration: 're2c:define:YYDISTTYPE' (use the new
directive '/*!contexts:re2c ... */' instead).
2016-04-01 17:04:12 +01:00
Ulya Trofimovich a72475dc4e Parser grammar cleanup.
- Rearranged some rules to avoid code duplication.
 - Added production and error message about contexts in named definitions.
 - Removed productions and error messages about missing expression
   (simple 'syntax error' is enough, given that only part of the
   errors was captured by the removed productions).
2016-03-29 22:37:44 +01:00
Ulya Trofimovich 7aac1ad2d4 Optimized pointer arithmetics generated with '-C, --contexts'.
If default input API is used and fixed-length context is based on
the rightmost context (that is, YYCURSOR), then the following expression
(that calculates pointer corresponding to the given context):
    (YYCTXMARKER + ((YYCURSOR - YYCTXMARKER) - yyctx))
can be optimized to:
    (YYCURSOR - yyctx)

Note: unfortunately, as of GCC < 7.0, expressions like:
    (YYCURSOR - 3) - (YYCURSOR - 5)
trigger warning:
    warning: integer overflow in expression [-Woverflow]
See this GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61240
2016-03-29 15:16:01 +01:00
Ulya Trofimovich f506af77bb Added some configurations related to '-C, --contexts' option.
Configurations:
    "define:YYCTX"      (defaults to 'YYCTX')
    "define:YYDIST"     (defaults to 'YYDIST')
    "define:YYDISTTYPE" (defaults to 'long')
    "ctxprefix"         (defaults to 'yyctx')
2016-03-29 12:54:02 +01:00
Ulya Trofimovich 7204740ab2 Use 'std::valarray' instead of 'std::vector' to avoid copy semantics.
Had to rename 'INFINITY' to 'SCC_INF': inclusion of '<valarray.h>'
pulled '<math.h>' and introduced name collision.
2016-03-28 19:59:23 +01:00
Ulya Trofimovich 81b5c9cb65 Use 'size_t' instead of 'uint32_t' to avoid 'static_cast'. 2016-03-28 15:49:07 +01:00
Ulya Trofimovich a0573b8314 Make sure that default rule is handled together with other rules. 2016-03-28 15:41:22 +01:00
Ulya Trofimovich 84bc67eeb3 Moved nontrivial context handling from parser to NFA construction phase.
Parser should simply construct AST; all the complex reasoning about
contexts (fixed vs variable) should be delayed until NFA is being
constructed. This way AST can be immutable and it's very easy to share
parts of AST between different conditions, etc.

Removed rule ranks and rank counter: rules are now stored in NFA-local
array and addressed by index.
2016-03-28 14:39:11 +01:00
Ulya Trofimovich 7db4babea0 Added partial submatch extraction.
Enabled with '-C, --contexts' option.

Warning '-Wselfoverlapping-contexts'.
2016-03-23 17:41:27 +00:00
Ulya Trofimovich 5a27bafae1 Moved loop counters out of skeleton; they belong to algorithm-local stuff. 2016-03-16 14:15:25 +00:00
Ulya Trofimovich 19e73705c5 Pack all stuff relevant to skeleton data generation in a struct. 2016-03-16 13:54:23 +00:00
Ulya Trofimovich 8989dae638 Use distinct type for path suffixes during skeleton data generation. 2016-03-16 12:20:25 +00:00
Ulya Trofimovich fffb5932ee Address skeleton nodes by indices rather than by pointers.
This way it is more convenient to add various graph algorithms:
each algorithm can keep its own data in array indexed by skeleton
node numbers (instead of pushing all relevant data inside of the
node).
2016-03-16 09:44:24 +00:00
Ulya Trofimovich c0afcbf19a Reuse the same struct to represent different kinds of paths in skeleton. 2016-03-15 13:25:32 +00:00
Ulya Trofimovich 6a8749cf2d [-Wundefined-control-flow] analyses: simplified path structure.
Now paths involved in [-Wundefined-control-flow] analyses have
exactly the same structure as paths involved in skeleton data generation.
2016-03-15 12:41:07 +00:00
Ulya Trofimovich 301ced0922 Added comments. 2016-03-15 08:28:02 +00:00
Ulya Trofimovich c3f4ba211d Moved comment. 2016-03-15 08:15:24 +00:00
Ulya Trofimovich 42b60fff68 Moved calculation of fallback states to earlier stage of DFA construction.
We will need this later, when adding multiple context markers
(liveness analyses during context marker deduplication).
2016-03-15 08:08:45 +00:00
Ulya Trofimovich a9cfb1b138 Eradicated occasional copy-paste.
Used function 'make_rule_copy' introduced by commit
f781c3a3a0.
2016-03-14 22:52:53 +00:00
Ulya Trofimovich afbd097ad8 Moved function definitions out of header. 2016-03-14 22:38:42 +00:00
Ulya Trofimovich 8dd79f3dde Skeleton: simplified path structure.
Just store pointers to skeleton nodes (instead of bookkeeping arcs,
contexts and rules in each path). All the necessary information can
be easily retrieved from nodes when path is baing dumped to file.

Three tests in '--skeleton' mode have been broken by this commit.
Actually, these are not breakages: these cases reveal incorrect
re2c-generated code. The change is due to the fact that skeleton
now doesn't simulate contexts that go *after* the matched rule:

    ------o------o------> ... (fallback to rule)
        rule   context
2016-03-14 22:23:03 +00:00
Ulya Trofimovich 87525eb8ea Skeleton: respect fixed-length contexts. 2016-03-14 21:45:42 +00:00
Ulya Trofimovich 16a376b54f run_tests.sh: fixed cleanup of intermediate files with '--skeleton'.
Broken by commit c56a14582d
"run_tests.sh: don't crash on absolute filepaths in test names."
2016-02-26 23:03:43 +00:00
Ulya Trofimovich c56a14582d run_tests.sh: don't crash on absolute filepaths in test names.
This patch fixes bug #137 "run_tests.sh fail when running configure
script with absolute path".

The fix: copy all test files into temporary build directory (which
is addressed by a relative filepath) and keep messing with relative
filepaths.
2016-02-24 17:12:31 +00:00
Ulya Trofimovich 7875e6c8e1 run_tests.sh: don't crash on absolute filepaths in test names.
This patch fixes bug #137 "run_tests.sh fail when running configure
script with absolute path".

The fix: copy all test files into temporary build directory (which
is addressed by a relative filepath) and keep messing with relative
filepaths.
2016-02-24 16:57:54 +00:00
Ulya Trofimovich f781c3a3a0 Code cleanup: moved rule construction to a separate file. 2016-02-22 15:47:44 +00:00
Ulya Trofimovich 5396689125 Mark rules as nullable rather than keep a separate collection of nullable rules. 2016-02-22 13:51:57 +00:00
Ulya Trofimovich 915296e178 Now regexp AST is immutable.
We don't do any transformations on AST anyway: it is analysed
and converted to NFA. This patch simply fixes the fact that AST
is immutable.
2016-02-22 13:17:57 +00:00
Ulya Trofimovich 2f643f40fa Code cleanup: replaced Regexp inheritance hierarchy with tagged union. 2016-02-22 13:03:38 +00:00
Ulya Trofimovich 4743c8fa36 Code cleanup: factored RuleInfo out of RuleOp.
Rule information (line, attached code block, rank, shadowing set, etc.)
is used throughout the program. Before this patch, rule information was
inlined in RuleOp. It was inconvenient because RuleOp belongs to early
stages of compilation (AST, prior to NFA), but it had to live throughout
the whole program.
2016-02-22 10:22:43 +00:00
Ulya Trofimovich 4c49568635 Simplified tracking of fixed-length trailing contexts.
Static (that is, of fixed length) trailing contexts don't need
recording context position with YYCTXMARKER and restoring it
back on successful match. They can be tracked simply by decreasing
input position by context length.
2016-02-17 16:12:59 +00:00
Ulya Trofimovich 551154584a Fixed an old bug in function calculating regexp length.
The bug: the function treated 'r1 | r2' as 'r1 | r2'
(used 'r1' twice instead of 'r1' and 'r2').

As the function was rarely used the bug went unnoticed for about
two decades.
2016-02-17 15:01:28 +00:00
Ulya Trofimovich 7e5550bc2e Simplified [-Wmatch-empty-rule] analyses.
Before this patch [-Wmatch-empty-rule] was based on:
    - DFA structural analyses (skeleton phase)
    - rule reachability analyses (skeleton phase)

Now it is based on:
    - NFA structural analyses (NFA phase)
    - rule reachability analyses (skeleton phase)

It's much easier to find nullable rules in NFA than in DFA.
The problem with DFA is in rules with trailing context, both
dynamic and especially static (as it leaves no trace in DFA
states). re2c currently treats static context as dynamic, but
it will change soon.

On the other side NFA may give some false positives because of
unreachable rules:
    [^] {}
    ""  {}
infinite rules:
    [^]* {}
or self-shadowing rules:
    [^]?
Reachability analyses in skeleton helps to filter out unreachable
and infinite rules, but not self-shadowing ones.
2016-02-17 14:46:43 +00:00
Ulya Trofimovich 3124a7994a run_tests.sh: avoid another '+=' in bash arrays (compatibility with old bash).
See #135 "In installation "make check" give syntax error".
2016-02-07 14:49:29 +00:00
Ulya Trofimovich aae1f2a4bf run_tests.sh: avoid '+=' in bash arrays (compatibility with old bash).
See #135 "In installation "make check" give syntax error".
2016-02-07 14:49:29 +00:00
Sergei Trofimovich b899b1f8c6 add basic support for travis-ci.org integration
Signed-off-by: Sergei Trofimovich <siarheit@google.com>
2016-02-07 13:43:32 +00:00
Sergei Trofimovich 68ef3eddea re2c/Makefile.am: use RST2MAN variable instead of hardcoded rst2man.py
Ubuntu installs docutils binaries without .py prefix.

Signed-off-by: Sergei Trofimovich <siarheit@google.com>
2016-02-07 12:01:32 +00:00
Ulya Trofimovich 051e365377 Release 0.16. 2016-01-21 10:48:30 +00:00
Ulya Trofimovich de7ff8ed7a Merged branch 'devel'. 2016-01-21 10:45:21 +00:00
Ulya Trofimovich f821ab7fed Updated CHANGELOG (preparing release 0.16). 2016-01-21 10:08:56 +00:00
Ulya Trofimovich 9573e0760c Makefile.am: fixed path to header. 2016-01-20 08:41:04 +00:00
Ulya Trofimovich 0331cce82d Removed forgotten 'typename' kewyword in non-template code. 2016-01-20 08:07:33 +00:00
Ulya Trofimovich e060774594 Fixed includes (applied some of 'include-what-you-use' suggestions). 2016-01-19 18:56:07 +00:00
Ulya Trofimovich b50ab61970 Applied #131: "Use bash-specific '[[' builtin". 2016-01-17 10:15:09 +00:00
Ulya Trofimovich 45d545e355 Stabilized the list of shadowing rules reported by [-Wunreachable-rules].
Before this commit, the list of rules depended on the order of NFA states
in each DFA state under construction (which is simply a matter of ordering
pointers to heap: the order can be different).

Now all rules for each DFA state are collected and the final choice of
rule is delayed until DFA is constructed, so the order of NFA states
no longer matters.
2016-01-16 23:14:29 +00:00
Ulya Trofimovich 23623243bb Merged two small headers into one. 2016-01-15 10:07:20 +00:00
Ulya Trofimovich 1014f1c756 Compact DFA states after minimization. 2016-01-13 09:12:14 +00:00
Ulya Trofimovich b54899592f Replaced class method with function. 2016-01-13 08:44:58 +00:00
Ulya Trofimovich 831c77af5f Keep data relevant to DFA determinization outsde of DFA states. 2016-01-13 08:14:38 +00:00
Ulya Trofimovich 1e78aad22a Moved YYFILL points calculation to the earlier stage of DFA construction.
No serious changes intended (mostly cleanup and comments).

The underlying algorithm for finding strongly connected components
(SCC) remains the same: it's a slightly modified Tarjan's algorithm.

We now mark non-YYFILL states by setting YYFILL argument to zero,
which is only logical: why would anyone call YYFILL to provide zero
characters. In fact, re2c didn't generate 'YYFILL(0)' call itself,
but some remnants of YYFILL did remain (which caused changes in tests).
2016-01-11 15:11:13 +00:00
Ulya Trofimovich a27179c535 Serialize '--skeleton' generated data in little-endian.
This commit fixes bug #132 "test failure on big endian archs with 0.15.3".

Tests failed because re2c with '--skeleton' option used host endianness
when serializing binary data to file. Expected test result was generated
on little-endian arch, while actual test was run on big-endian arch.

Only three tests failed (out of ~40 tests that are always run with
'--skeleton'), because in most cases data unit is 1 byte and endianness
doesn't matter.

The fix: re2c now converts binary data from host-endian to little-endian
before dumping it to file. Skeleton programs convert data back from
little-endian to host-endian when reading it from file (iff data unit
size is greater than 1 byte).
2016-01-07 15:20:37 +00:00
Ulya Trofimovich de094eba9f Serialize '--skeleton' generated data in little-endian.
This commit fixes bug #132 "test failure on big endian archs with 0.15.3".

Tests failed because re2c with '--skeleton' option used host endianness
when serializing binary data to file. Expected test result was generated
on little-endian arch, while actual test was run on big-endian arch.

Only three tests failed (out of ~40 tests that are always run with
'--skeleton'), because in most cases data unit is 1 byte and endianness
doesn't matter.

The fix: re2c now converts binary data from host-endian to little-endian
before dumping it to file. Skeleton programs convert data back from
little-endian to host-endian when reading it from file (iff data unit
size is greater than 1 byte).
2016-01-07 14:24:52 +00:00
Ulya Trofimovich 615773a3ee configure.ac: fixed error message.
Message should report 'rst2man' as well as 'rst2man.py'.
2016-01-06 10:11:39 +00:00
Ulya Trofimovich c105527ab4 configure.ac: check for 'rst2man' as well as 'rst2man.py'.
Fixes bug #133 "rst2man.py depreciated in RHEL7".
2016-01-06 09:21:57 +00:00
Ulya Trofimovich cfe14bc4df Explicitely handle default state as special case during DFA construction. 2016-01-05 17:15:37 +00:00
Ulya Trofimovich ec0a3f36ef Check accumulated parameter before entering recursion. 2016-01-02 17:27:45 +00:00
Ulya Trofimovich 4769678112 Renamed files and function. 2016-01-01 10:11:56 +00:00
Ulya Trofimovich 59f71683e6 Moved source subdirectory. 2015-12-31 22:06:13 +00:00
Ulya Trofimovich ea31a0782a Moved source files to a proper subdirectory. 2015-12-31 21:52:54 +00:00
Ulya Trofimovich 47d82442aa Removed obsolete code deduplication mechanism.
This mechanism was tricky and fragile; it cost us a most unfortunate
bug in PHP lexer: https://bugs.gentoo.org/show_bug.cgi?id=518904
(and a couple of other bugs).

Now that re2c does DFA minimization this is no longer needed. Hoooray!

The updated test changed because skeleton is constructed prior to
DFA minimization.
2015-12-31 21:17:32 +00:00
Ulya Trofimovich cd0937c79b Removed obsolete comments. 2015-12-31 20:56:41 +00:00
Ulya Trofimovich c604db18b9 Added test for bug #128 "very slow DFA construction (resulting in a very large DFA)".
After minimization the resulting DFA is much smaller:
    /*!re2c
        [ac]{0,14} [a] [ac]{0,14} {}
    */

Was:
    $ time re2c slow.re > slow.c && stat -c '%s' slow.c

    real    1m54.837s
    user    1m54.733s
    sys     0m0.120s
    5627102

Now:
    $ time ./re2c slow.re > slow.c && stat -c '%s' slow.c

    real    0m0.732s
    user    0m0.684s
    sys     0m0.048s
    15078
2015-12-31 20:20:35 +00:00
Ulya Trofimovich 1136f2fb00 Added DFA minimization and option '--dfa-minimization <table | moore>'.
Test results changed a lot; it is next to impossible to verify them
by hand. I therefore implemented two different minimization algorithms:
    - "table filling" algorithm (simple and inefficient)
    - Moore's algorithm (not so simple and efficient enough)
They produce identical minimized DFA (up to states relabelling), thus
giving some confidence in that the resulting DFA is correct.

I also checked the results with '--skeleton': re2c constructs
skeleton prior to reordering and minimization, therefore
skeleton-generated data is free of (potential) minimization errors.
2015-12-31 15:35:30 +00:00
Ulya Trofimovich fdd15074af Split DFA intermediate representation in two parts: DFA and ADFA.
ADFA stands for 'action DFA', that is, DFA with actions.

During DFA construction (aka NFA determinization) it is convenient
to represent DFA states as indexes to array of states.
Later on, while binding actions, it is more convanient to store
states in a linked list.
2015-12-30 20:52:33 +00:00
Ulya Trofimovich caf00b33d4 Merge branch 'master' of git://github.com/jcfp/re2c
*  missed some occurrences...
2015-12-21 14:29:20 +00:00
jcfp 37b118d79c missed some occurrences... 2015-12-21 14:25:49 +01:00
Ulya Trofimovich 0a9eb7553d Merge branch 'master' into devel 2015-12-21 11:51:47 +00:00
Ulya Trofimovich 4843e15ecc Merge branch 'jcfp-master' 2015-12-21 11:46:46 +00:00
jcfp 13d3abb58f typ0 fixes 2015-12-21 11:57:59 +01:00
Ulya Trofimovich b98997b6fe Keep DFA states in a hash map (to speedup lookup fo an identical state).
This partially fixes bug #128: "very slow DFA construction (resulting
in a very large DFA)". DFA construction is no longer slow, but the
resulting DFA is still too large and needs to be minimized.
2015-12-19 17:17:00 +00:00
Ulya Trofimovich 41f17b5bd6 DFA construction: epsilon-closure of NFA states: pick only kernel states. 2015-12-18 21:48:27 +00:00
Ulya Trofimovich 45066b3a3a Changed bytecode intermediate representation to a simpler NFA representation. 2015-12-18 12:52:17 +00:00
Ulya Trofimovich 5cf441dc93 Base '+' (one or more repetitions) on '*' (zero or more repetitions).
Kleene star '*' (aka iteration, repetition, etc.) is a primitive
operation in regular expressions.

For some reason re2c used '+' as a primitive operation and expressed
'*' in terms of '+'. It is inconvenient, because all algorithms
described in literature are based on '*'.

Because we now express 'a+' as 'a* a', we have to set 'PRIVATE' attribute
on 'a': otherwize 'a' gets shared between the two occurences which causes
complex bugs.

Expressing 'a+' in a more intuitive way as 'a a*' rather than 'a* a'
causes the generated code to duplicate certain states. The generated code
is (supposedly correct), but re2c fails to deduplicate these states.
We therefore prefer 'a* a' expansion, which results in exactly the same
code as before.
2015-12-15 12:44:47 +00:00
Ulya Trofimovich 70b7e09fb6 No need to preserve special order of states while building DFA (thanks to states reordering). 2015-12-14 14:33:21 +00:00
Ulya Trofimovich bd41dc7a8c Dropped the difference between left and right default rule (thanks to states reordering).
Bootstrap lexer changed a lot: this change is caused by commit
a4c192f27a: "Reordered states in DFA.".
Changes in parser by this commit triggered lexer regeneration.
2015-12-14 14:21:13 +00:00
Ulya Trofimovich a4c192f27a Reordered states in DFA. 2015-12-14 13:59:34 +00:00
Ulya Trofimovich 4fa27cf7b4 Fixed bug #127: "code generation error with wide chars and bitmaps (omitted 'goto' statement)".
Minimal test case:
    /*!re2c
        [^a]+ {}
        [a]   {}
    */

Catched with skeleton:
    $ re2c -W -ubi err.re -S -o err.c && gcc err.c -o err && ./err
    error: lex_line4: at position 294 (iteration 98):
            expected: match length 2, rule 0
            actual:   match length 1, rule 1
2015-12-09 11:22:08 +00:00
Ulya Trofimovich ea50dd75f1 Simplified handling of character ranges in DFA construction algorithm.
Now disjoint character ranges in bytecode are represented using
range index rather than range lower bound (as it used to be).
2015-12-05 22:39:12 +00:00
Ulya Trofimovich 173bdfa36f Optimized charset representation.
re2c used a complex and slow algorithm to split charset into
disjoint character ranges. This commit replaces old algorithm with
new (much simpler and quicker).

re2c test suite now runs 2x faster due to speedup in Unicode tests.
2015-12-05 10:15:23 +00:00
Ulya Trofimovich df19195968 Release 0.15.3. 2015-12-02 12:11:01 +00:00
Ulya Trofimovich 74cb8ddb6d Prepare release 0.15.3: updated CHANGELOG. 2015-12-01 17:49:06 +00:00
Ulya Trofimovich 99323fc37c Added description of '--no-version' option to help and manpage. 2015-12-01 17:45:59 +00:00
Ulya Trofimovich d51b2592f8 Fixed '#include's (appied most of 'include-what-you-use' suggestions).
The worst dependency which 'include-what-you-use' fails to see
(and rightly so) is 'src/parse/lex.re' -> 'src/parse/parser.h'.
This dependency is caused by '#include "y.tab.h"' in 'src/parse/lex.re'.

Another ubiquitos issue is 'src/util/c99_stdint.h' ('include-what-you-use'
suggests to substitute it with '<stdint.h>').

And a couple of other dependencies that 'include-what-you-use' fails to see.
2015-12-01 16:14:49 +00:00
Ulya Trofimovich 776c9bf516 Prefixed all tokens with 'TOKEN_'.
Inspired by commit commit c172f266b4.
2015-12-01 12:59:54 +00:00
Ulya Trofimovich c24b4fe9bd Makefile.am: use 'AM_V_GEN' prefix to report custom rules. 2015-12-01 12:42:42 +00:00
Ulya Trofimovich 86ba9fa398 run_tests.sh (with '--skeleton'): clarified message, use generic CC rathen than 'gcc'. 2015-12-01 12:10:49 +00:00
Ulya Trofimovich 06fa1d825f Renamed tests that contained uppercase letters in file extension.
We use file extensions to encode re2c options.
Some (short) options are uppercase letters: e.g. '-D', '-F', '-S'.
There also short options for the same lowercase letters: '-d', '-f', '-s'.
This can cause filename collisions on platforms with case-insensitive
file extensions (e.g. Windows and OS X).

See bud #125: "[OS X] git reports changes not staged for commit
in newly cloned repository".

Fix: use long versions for options that uppercase options.
Disallowed uppercase options in 'run_tests.sh'.
2015-11-30 22:50:23 +00:00
Ulya Trofimovich 4c7a3c83c1 configure.ac: suppress some warnings with '-Weverything'. 2015-11-30 21:44:09 +00:00
Ulya Trofimovich 3cf9335f80 '-Wundefined-control-flow': fixed patterns ordering, reduced memory consumption.
The problem with pattern ordering first emerged on FreeBSD-10.2
(I was able to reproduce it with 'CXXFLAGS=-fsanitize=address').
Some tests failed because patterns reported by '-Wundefined-control-flow'
were sorted in different order than expected. This is because
patterns ordering was inconsistent: patterns were compared by length,
(it doesn't work for patterns of equal length). Now first ordering
criterion is length, and second criterion is lexicographical order.

This commit reduces the amount of memory consumed by '-Wundefined-control-flow':
re2c no longer allocates vectors on stack while deep-first-searching skeleton.

This commit also reduces the limit of memory for '-Wundefined-control-flow'
(64Mb edges -> 1Kb edges). Real-world programs rarely need that much.
The limit was so high to acommodate some few artificial tests (with lower
limit these tests cannot find shortest patterns).

This commit also removes the upper bound for the number of faulty patterns
reported by '-Wundefined-control-flow'. This bound was needed by the
artificial tests mentioned above: they produce lots of patterns.
Now these tests are limited with 1Kb of edges anyway.

Note that 1Kb limit is checked after each new pattern is added, so that
at least one pattern will fit in (even if it takes more than 1Kb).
2015-11-30 12:12:44 +00:00
Ulya Trofimovich 629a7a71ff Removed one particularly fat test from test collection. 2015-11-29 13:58:20 +00:00
Ulya Trofimovich a4d2cc0419 Substitute template class with non-template, as only one specialization is used. 2015-11-29 13:58:19 +00:00
Ulya Trofimovich d314f55b0c Skeleton data generation: suffix should be multipath as well as prefix.
Prefix of current path under construction is a multipath, because prefix
arcs have not been covered yet. Suffix can be a simple path (that is, a
multipath of width 1), because all alternative suffix arcs have already
been covered.

prefix       suffix
_________   _________
...      \ /
--------- o
_________/

But nothing prevents us from alternating suffix arcs also, as long as
suffix remains a single multipath:

_________   _________
...      \ / ...
--------- o ---------
_________/ \_________

The resulting path's width is the maximum of prefix ans suffix width
(hence the growth in size of those tests in which suffix is wider
than prefix), but it only makes a small difference. And the generated
paths are more "variable".
2015-11-29 13:58:19 +00:00
Ulya Trofimovich 3962cf0456 Skeleton data generation: cover all edges in 1-byte range (not only range bounds).
If code units occupy 1 byte, then the generated path cover covers
*all* edges in the original DFA. If the size of code unit exceeds 1 byte,
then only some ~0x100 (or less) range values will be chosen
(including range bounds).
2015-11-29 13:58:17 +00:00
Ulya Trofimovich e36675342f Skeleton data generation: dropped exponential algorithm, always use path cover. 2015-11-29 13:58:16 +00:00
Ulya Trofimovich 9a5f154188 Removed obsolete '__STDC_LIMIT_MACROS' and '__STDC_CONSTANT_MACROS' defines.
These defines were necessary to enable numeric limits definitions
(such as 'UINT32_MAX') in our local version of 'stdint.h' (which is
used on platforms that don't have system header 'stdint.h').

As noted by commit b237daed20, this
workaround doesn't work on FreeBSD, so re2c now uses 'numeric_limits.h'.
2015-11-29 11:38:04 +00:00
Ulya Trofimovich d3d2230d1d Fixed [-Wconversion] warning.
Warning was introduced in commit b237daed20:
compiler fails to recognise (or deliberately choses not to recognize)
'std::numeric_limits<...>::max()' as a special constant.
2015-11-29 11:24:48 +00:00
Ulya Trofimovich bae5b14de9 run_tests.sh: use '--no-version --no-generation-date' instead of sed hack.
These options make re2c omit version and date info and thus produce
stable test results.
2015-11-29 11:04:56 +00:00
Ulya Trofimovich 2aae55c656 Added option '--no-version' that omits version in fingerprint. 2015-11-29 10:57:47 +00:00
Sergei Trofimovich b237daed20 Get rid of UINT32_MAX and friends
UINT32_MAX is conditionally defined only
for C compiler on FreeBSD but not for C++,

Stop using __STDC_LIMIT_MACROS workaround
as it does not work on FreeBSD.

Use std::numeric_limits<> from C++98 instead.

Signed-off-by: Sergei Trofimovich <siarheit@google.com>
2015-11-28 18:31:59 +00:00
Ulya Trofimovich 8a361fe0b3 Fixed crashes of 'ostream& operator<< (ostream& os, const char* s)' on NULL.
Crashes observed on platforms OS X (clang-7.0.0) and FreeBSD-10.2 (clang-3.4).
First reported in bug #122 "clang does not compile re2c 0.15.x".

What caused NULL passed to 'operator <<': re2c always generates content of
header file (regardless of '-t --type-header' option), but the content is
dumped to file (and header filename initialized to non-NULL) only if the
option was enabled.

Fix: always initialize header filename to non-NULL string.
2015-11-28 17:31:56 +00:00
Ulya Trofimovich 2daef3c279 run_tests.sh: use '/usr/bin/env bash' to locate bash. 2015-11-28 15:44:04 +00:00
Ulya Trofimovich d80507eadd Makefile.am: use '=' instead of '==' to compare strings.
'==' appears to be a bash feature.
2015-11-28 15:39:56 +00:00
Ulya Trofimovich f65caba520 Don't use overloaded constructors with integral types.
This causes ambiguity in overload resolution on OS X:

    src/codegen/skeleton/generate_data.cc:308:30: error: ambiguous conversion for functional-style cast from 'const size_t' (aka 'const unsigned long') to 'Node::covers_t'
          (aka 'u32lim_t<1024 * 1024 * 1024>')
            const Node::covers_t size = Node::covers_t (len) * Node::covers_t (count);
                                        ^~~~~~~~~~~~~~~~~~~
    ./src/util/u32lim.h:20:11: note: candidate constructor
            explicit u32lim_t (uint32_t x)
                     ^
    ./src/util/u32lim.h:23:11: note: candidate constructor
            explicit u32lim_t (uint64_t x)

Use static constructor-like methods with expliit names.
2015-11-28 11:36:41 +00:00
Oleksii Taran c172f266b4 Fix "CODE" symbol collision on OS X (see #122)
On OS X bison generates token enums as CPP macro
constants (y.tab.h):
    #define CODE 260
while on my box it's
   enum yytokentype {
     ...
     CODE = 260,
     ...
   };

That #define causes symbol collision as:

    ../src/parse/lex.re:169:38: error: expected unqualified-id
                                            else if (opts->target == opt_t::CODE)
                                                                            ^
    src/parse/y.tab.h:58:14: note: expanded from macro 'CODE'
    #define CODE 260

Renamed enum entry to TOKEN_CODE.
2015-11-28 10:52:47 +00:00
Ulya Trofimovich bedb784318 Allowed chaining for all 'OutputFile' methods; renamed them in a uniform way. 2015-11-27 14:29:16 +00:00
Ulya Trofimovich 1872278498 Use local re2c (in '$(top_bulddir)') rather than system re2c for 'make bootstrap'.
Correct behaviour was broken by commit 38f526d044.
2015-11-27 13:58:29 +00:00
Ulya Trofimovich 499537c8f3 Don't use 'operator <<' overloads with integral types: resolution is platform-dependent.
See bug #122 "clang does not compile re2c 0.15.x".

Example of error on Mac OS X:
    src/codegen/emit_dfa.cc:250:65: error: use of overloaded operator '<<' is ambiguous (with operand types 're2c::OutputFile' and 'const size_t'
          (aka 'const unsigned long'))
            o << indent(ind++) << "static void *" << opts->yyctable << "[" << conds << "] = {\n";
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~~~~
    ./src/codegen/output.h:84:22: note: candidate function
            friend OutputFile & operator << (OutputFile & o, char c);
                                ^
    ./src/codegen/output.h:85:22: note: candidate function
            friend OutputFile & operator << (OutputFile & o, uint32_t n);
                                ^
    ./src/codegen/output.h:86:22: note: candidate function
            friend OutputFile & operator << (OutputFile & o, uint64_t n);
                            ^

On OS X 'size_t' is neither 'uint32_t' nor 'uint64_t', resolution is therefore ambiguous.
2015-11-27 13:41:42 +00:00
Ulya Trofimovich 0daf0c3601 Release 0.15.2. 2015-11-23 21:20:12 +00:00
Ulya Trofimovich d7db8c79c5 Prepare release 0-15.2: updated CHANGELOG. 2015-11-23 21:15:38 +00:00
Ulya Trofimovich 88a7cec2e6 Makefile.am: lexer dependends on bison-generated parser; fixed rule order. 2015-11-23 21:11:19 +00:00
Ulya Trofimovich 4b0472104c Release 0.15.1. 2015-11-22 21:03:29 +00:00
Ulya Trofimovich 80726de48d Prepare release 0.15.1: updated CHANGELOG. 2015-11-22 20:59:29 +00:00
Ulya Trofimovich 3c2b39a06b run_tests.sh: fix the order of files in test results.
'sort' behavior depends on current locale; set 'LC_ALL=C LANG=C'
before doing locale-sensitive things. Updated test results.
2015-11-22 20:55:04 +00:00
Ulya Trofimovich 1fc30a036e release.sh: don't forget to push tags. 2015-11-22 20:50:15 +00:00
Ulya Trofimovich 8f32d427f0 Release 0.15. 2015-11-22 19:53:04 +00:00
Ulya Trofimovich 708d893a00 Prepare release 0.15: updated release instructions. 2015-11-22 19:48:37 +00:00
Ulya Trofimovich d8bde4393e Prepare release 0.15: updated CHANGELOG. 2015-11-22 19:46:45 +00:00
Ulya Trofimovich 0762f699e3 Use 'rst2man.py' to build manpage; updated manpage. 2015-11-22 19:42:21 +00:00
Ulya Trofimovich 7344163c00 Merge branch 'master' into simplified_codegen.
* master:
  Updated version to 0.14.4.dev
  Release 0.14.3.
  Added simple test for yacc-style brackets (see patch #27)
  Fixed '#27 re2c crashes reading files containing %{ %}' (patch by Rui)
  Makefile.am: dropped distfiles for MSVC (they are broken anyway)
  Added full another test for bug #57.
  Updated version to 0.14.3.dev
  Release 0.14.2.
  Fixed bug #57: Wrong result only if another rule is present
  Updated version to 0.14.2.dev
  Release 0.14.1.
  Pad version with '0' instead of nulls
2015-11-21 20:03:10 +00:00
Ulya Trofimovich af5a8a332e Skeleton: data generation (linear): don't forget to dump path in end nodes. 2015-11-18 14:45:49 +00:00
Ulya Trofimovich c1fefc0264 Skeleton: changed formatting of the generated code (no significant changes). 2015-11-16 14:48:53 +00:00
Ulya Trofimovich fb08a3f8ae Skeleton: disregard default rule when estimating maximum rule size (in bytes).
Default rule '*' (not to be confused with 'none' rule) used to have
normal number just like other rules. Now that re2c has to distinguish
default rule fro other rules (because of [-Wunreachable-rules]),
it reserves a special number (UINT32_MAX - 1) for it.
2015-11-16 14:10:49 +00:00
Ulya Trofimovich c50bae1052 Lex strings and character classes in a more elegant way. 2015-11-10 15:28:28 +00:00
Ulya Trofimovich 26110738a0 Recognize escaped dash '\-' in character class. 2015-11-09 16:06:40 +00:00
Ulya Trofimovich fcd9ff70e9 Fixed tests for bug #119: "-f with -b/-g generates incorrect dispatch on fill labels".
Somehow configuration 're2c:state:abort = 1;' was present in all the
tests; it was meant to be only in half of them.
2015-10-16 13:21:50 +01:00
Ulya Trofimovich 2b3564298d run_tests.sh: tried to clarify regexp that splits options from filename.
Note: should keep to POSIX, so no '+' or '?' is allowed.
2015-10-15 14:54:17 +01:00
Ulya Trofimovich 1814823910 run_tests.sh: run each test in a separate directory and paste all generated files into one.
Updated tests: changes are insignificant (the order in which multiple
generated files are concatenated has changed).
2015-10-14 23:11:01 +01:00
Ulya Trofimovich 2b2182adaa run_tests.sh: don't change filenames to '<stdout>'.
Updated test. Used the following shell script to validate changes:

    #!/bin/bash

    for f2 in *.temp
    do
        f1=${f2%.temp}

        diff1=`diff $f1 $f2 | grep '^< ' | wc -l`
        diff1_fname=`diff $f1 $f2 | grep '^<\( #line [0-9]\+ "<stdout>"\|[ ]\+("<stdout>[^"]\+"\)' | wc -l`
        diff2=`diff $f1 $f2 | grep '^> ' | wc -l`
        diff2_fname=`diff $f1 $f2 | grep '^>\( #line [0-9]\+ "[^"]\+"\|[ ]\+("[^"]\+"\)' | wc -l`

        # missing: only changed filenames
        [ $diff1 -ne $diff1_fname ] && echo "FAIL1: $f1" && exit 1

        # added: only changed filenames
        [ $diff2 -ne $diff2_fname ] && echo "FAIL2: $f1" && exit 1

        # the number of missing changed filenames
        # equals to the number of added changed filenames
        [ $diff1_fname -ne $diff2_fname ] && echo "FAIL4: $f1" && exit 1
    done

    echo "OK"
2015-10-14 15:09:41 +01:00
Ulya Trofimovich 6d88f7b69a run_tests.sh: paste type headers into source file and diff all at once. 2015-10-14 14:19:55 +01:00
Ulya Trofimovich ca1e8812ca run_tests.sh: use '-o' option. Added tests for '--skeleton' option. 2015-10-14 13:04:19 +01:00
Ulya Trofimovich ac37dfc421 Omit unnecessary null pointer check (suggested by Markus Elfring). 2015-10-13 21:20:22 +01:00
Ulya Trofimovich 9e8c141486 run_tests.sh: added option '--keep-tmp-files'. 2015-10-13 15:36:44 +01:00
Ulya Trofimovich 8306becfbf run_tests.sh: added '--skeleton' option.
With this option script runs re2c with '--skeleton' and
'-Werror-undefined-control-flow' and instead of comparing results with
reference test results, it compiles the generated skeleton programs and
runs them. If C compiler or binary return nonzero error status, script
reports an error. Note that cases when re2c failed to generate code are
not considered errors (re2c has lots of test cases for its errors).
2015-10-13 14:26:33 +01:00
Ulya Trofimovich f11005aed2 Split main lexer and configuration lexer in two separate files. 2015-10-12 15:35:42 +01:00
Ulya Trofimovich 70e51a94d5 Factored out some common lexing pieces into separate routines.
re2c lacks submatch extraction; it would be much more convenient
to memorize input positions for some parts of regular expressions
than break each regexp in the middle and move parts to separate blocks.

Submatch extraction is dificult to implement in general, but supporting
submatch in some simple cases (like the case where trailing context is
allowed) would be not so difficult and most helpful.
2015-10-12 14:12:11 +01:00
Ulya Trofimovich 15bfced936 Parse inplace configurations in lexer; don't pass them to parser.
This removes a lot of copy-pasting.

The change of error location in test is insignificant: the reported
location was incorrect and it still remains imprecise.
2015-10-12 13:56:07 +01:00
Ulya Trofimovich 24437fb4c5 Improved '-Wmatch-empty-string' warning.
- recognize empty match with nonempty trailing context
- don't report unreachable empty match
2015-10-08 14:38:19 +01:00
Ulya Trofimovich 985da16c25 Added '-Wunreachable-rules' warning.
Warns about unreachable rules:
  - rules that are shadowed by other rules, e.g. rule '[a]' is shadowed by
    '[a] [^]'
  - infinite rules that consume infinitely many characters and fail on
    YYFILL, e.g. '[^]*'
  - rules that contain never-matching link, e.g. '[]' with option
    '--empty-class match-none'
default rule '*' should not be reported
2015-10-08 11:39:25 +01:00
Ulya Trofimovich 71e31931f5 Fixed memleaks and grouped options in one big macro. 2015-10-07 18:30:19 +01:00
Ulya Trofimovich 573c077962 Merge default rules on the fly, assign them the same lowest priority.
re2c used to postpone merging default rules because rank counter could
only assign consequtive ranks to rules, and default rules must have
the lowest priority. Now rank counter has been modified to return
special value as defult rule rank.
2015-10-07 16:20:38 +01:00
Ulya Trofimovich 5af7cf83db Autogenerated configuration tests: added default rule to each test.
It's not a bunch of unnecessary warnings I want to avoid, it's a bunch of
unnecessary runtime failures in programs generated with '--skeleton'
(failures caused by undefined control flow; re2c recogizes such cases
and the generated program reports a warning before failing).
2015-10-05 21:27:24 +01:00
Ulya Trofimovich 60a8dfff96 Support trailing context with '--skeleton'.
Trialing contexts are currently broken (overlapping trailing contexts
cannot be tracked with a single 'YYCTXMARKER'). For now, re2c with
'--skeleton' mimics this incorrect behaviour: information about context
is lost by the time DFA is constructed, so skeleton has no way to
figure out the right order of things.
2015-10-05 15:44:50 +01:00
Ulya Trofimovich a0a9b3ba0b Moved path-combining magic closer to path definition. 2015-10-04 19:46:34 +01:00
Ulya Trofimovich 14911dbae5 Fixed bug #116: "empty string with non-empty trailing context consumes code units".
Prior to this commit backup of trailing context position was done
before advancing input position and re2c either had to emit
    YYCTXMARKER = YYCURSOR + 1;
(with default input API), or
    YYRESTORECTX ();
    YYSKIP ();
(with custom input API).

The problem is that sometimes initial state doesn't sdvance input position
at all. Now re2c emits context backup after advancing input position and it
no longer needs '+1' or 'YYSKIP' hacks. It always backups the correct position.
2015-10-04 19:25:00 +01:00
Ulya Trofimovich 7f7121334b '--skeleton': don't forget to jump to start label when needed. 2015-09-30 17:33:58 +01:00
Ulya Trofimovich 32509f16d5 '--skeleton': give more info when reporting unused data and keys. 2015-09-30 17:04:29 +01:00
Ulya Trofimovich 38d1eec17d '--skeleton': fixed codegen error with '-b' (don't forget last bitmap element). 2015-09-30 16:12:27 +01:00
Ulya Trofimovich 609a7db2bf '--skeleton': added missing newline in the generated code. 2015-09-30 16:11:45 +01:00
Ulya Trofimovich 58f53a4f3a '--skeleton': tell function name when reporting errors and warnings. 2015-09-30 16:10:38 +01:00
Ulya Trofimovich afd7fe7a8b '--skeleton': respect empty string match. 2015-09-29 16:47:25 +01:00
Ulya Trofimovich a000e8c3a2 Fixed skeleton generation in '-r' mode.
'-r' is different from normal mode in two aspects:
    - single DFA may be used multiple times (unchanged, we only
      need a single copy for skeleton)
    - DFA may be generated but not used at all
2015-09-29 16:04:27 +01:00
Ulya Trofimovich 078bf68445 Split skeleton arc count limits for permutations, cover and default paths. 2015-09-28 22:34:06 +01:00
Ulya Trofimovich 18e388490d Docs: updated descriptions of some inplace configurations. 2015-09-28 15:30:20 +01:00
Ulya Trofimovich e65aff4ec8 Unified meaning and mutual relations of some inplace configurations.
This commit changes the behaviour of three groups of options:

    re2c:define:YYSETCONDITION
    re2c:define:YYSETCONDITION@cond
    re2c:define:YYSETCONDITION:naked

    re2c:define:YYSETSTATE
    re2c:define:YYSETSTATE@state
    re2c:define:YYSETSTATE:naked (added by this commit)

    re2c:define:YYFILL
    re2c:define:YYFILL@len
    re2c:yyfill:parameter
    re2c:define:YYFILL:naked

The changes should be backwards compatible (meaning that old code that
compiled should still compile), but it may add empty statements or statements
with no effect for some configurations, e.g.:
    YYSETCONDTITION(0);(0);
These changes were necessary to unify re2c behaviour, remove counter-intuitive
cases and make it possible to write comprehensible option descriptions.

In short, the changes are:
    - 'naked' triggers generation of argument-in-braces and semicolon;
    - 'parameter' triggers generation of argument-in-braces (when applicable,
      'naked' has priority over 'parameter');
    - argument templates ('@cond', '@state', '@len') don't force other
      configurations, they also don't influence on argument-in-braces;

Added test generator and autogenerated tests.
2015-09-28 13:54:26 +01:00
Ulya Trofimovich 91736dd4a7 run_tests.sh: preserve nested directory structure when dumping errors. 2015-09-28 13:49:05 +01:00
Ulya Trofimovich 27a83c0ffd Don't hang forever trying to replace empty configuration arguments. 2015-09-27 12:03:03 +01:00
Ulya Trofimovich f18bc190be Default options should be syncronized as well. 2015-09-27 11:58:40 +01:00
Ulya Trofimovich 10f3fd13ba Reduced redundant global flags. 2015-09-24 15:21:45 +01:00
Ulya Trofimovich e648ecbb30 Handle all inplace configurations in a uniform way.
This commit removes check (and error) for overwritten configurations
(like setting 're2c:define:YYCYRSOR' twice in the same block).
This check was in principle useful, but it was applied to somehow
randomly chosen set of parameters. If in future we'll feel a need
for such check, it should respect all options equally and report
warning rather than error.
2015-09-24 14:52:24 +01:00
Ulya Trofimovich 00c6e36ff2 Automatically resync options on read acccess (if they have been updated). 2015-09-23 22:08:39 +01:00
Ulya Trofimovich a72a824bbe Merged 'DFlag' and 'flag_skeleton' into one option 'target'.
The nature of these options makes them mutually exclusive; so instead
of checking that they are not both set just make them a single option.
2015-09-23 17:32:36 +01:00
Ulya Trofimovich 70e15e0455 Separated user config and effective config. 2015-09-23 15:45:54 +01:00
Ulya Trofimovich 12b25c9588 Prepare to separate user config and effective config. 2015-09-22 13:15:31 +01:00
Ulya Trofimovich 5034e81fe7 Keep name table together with other options. 2015-09-21 22:14:45 +01:00
Ulya Trofimovich ad444e1c14 Grouped options together in a struct. 2015-09-21 21:50:55 +01:00
Ulya Trofimovich 1656bccc9c Documentation: added warning descriptions to manpage and online manual. 2015-09-17 15:16:38 +01:00
Ulya Trofimovich 0837ad250c Documentation: added warning descriptions to '-h, -?, --help' option. 2015-09-17 15:03:24 +01:00
Ulya Trofimovich b2794e362b Removed unused method declaration. 2015-09-17 13:55:46 +01:00
Ulya Trofimovich 70f1cb9628 Gather some DFA statistics and use it to omit unused code with '--skeleton'. 2015-09-17 13:52:09 +01:00
Ulya Trofimovich 1d1bfcde05 Omit usseless 'yyaccept' variable in '--skeleton' programs.
Normally re2c generates single 'yyaccept' variable for all conditions.
With '--skeleton' re2c handles conditions separately, so each condition
needs (or needs not) its own 'yyaccept'.

Prior to this commit re2c used the same criterion to determine if
'yyaccept' is needed with '--skeleton' as it uses generally: whether
'yyaccept' was used in any of conditions. Now re2c looks if 'yyaccept'
was used with this particular condition.
2015-09-17 10:53:35 +01:00
Ulya Trofimovich cdca7f7189 Generate better code with '--skeleton': C90-compliant, free resources on errors. 2015-09-17 10:27:57 +01:00
Ulya Trofimovich 509102d602 Check 'fread' return value in program generated with '--skeleton'. 2015-09-16 12:19:28 +01:00
Ulya Trofimovich 740b53ee1f Support '--skeleton' with conditions and multiple re2c blocks. 2015-09-16 11:25:29 +01:00
Ulya Trofimovich c41a737ff2 Make 'filesize' function for '--skeleton' preserve original file position. 2015-09-15 13:35:27 +01:00
Ulya Trofimovich 18b1c48a4c Fixed MINGW builds where 'sizeof (int)' is equal to 'sizeof (long)'. 2015-09-15 13:08:10 +01:00
Ulya Trofimovich 6e8c0d50db Changed '-Wcondition-order' to warn even if 'YYSETCONDITION' is used.
Tests 'condtype_yysetcondition.c{s,g}.re' show the reason why I changed
how '-Wcondition-order' works in presence of 'YYSETCONDITION' calls:
programs generated from these tests work differently depending on
condition numbering. Explicit use of condition names cannot guarantee
that these explicit names were generated by re2c (and not hardcoded as
in these examples).
2015-09-15 11:51:36 +01:00
Ulya Trofimovich e86c36700d More accurate handling of default rule for '--skeleton'. 2015-09-15 10:45:19 +01:00
Ulya Trofimovich d765e9cb51 The generated '--skeleton' program now warns about undefined control flow. 2015-09-14 23:11:51 +01:00
Ulya Trofimovich a239ab0e39 Fixed error in calculation of maximal path length in skeleton. 2015-09-14 15:28:52 +01:00
Ulya Trofimovich ae65600796 Compacted keys representation (with '--skeleton').
Determine maximal path length and maximal rule number while constructing
skeleton; take maximim of these two values; choose unsigned integer type
of minimal width capable of holding maximim.

Note: re2c operates on exact-width integers, but the generated program
doesn't (it might not have <stdint.h>). When generating the program,
re2c choses one of unsigned 'char', 'short', 'int' and 'long' types
(that one 'sizeof' which is equal to the disired key size). re2c makes
some implicit assumptions (generated program is run on the same platform
as re2c, byte consists of 8 bits, etc.). Perhaps re2c should hardcode
these assumptions in the generated program and check them on start.
2015-09-14 13:19:15 +01:00
Ulya Trofimovich 29859ce865 Store keys for '--skeleton' in binary.
A single key is formed of three values:
    1. the length of string
    2. the length of matched part of string
    3. the number of matched rule
All these values are guaranteed to fit 32 bits, so for now we just
dump them as 'uint32_t' and read as 'unsigned int'. re2c asserts that
'sizeof (uint32_t) == sizeof (unsigned int)'.

Avoid structs, as they cause padding issues.
2015-09-11 18:48:35 +01:00
Ulya Trofimovich 73cbfc9300 Estimate maximal path length in skeleton and abort if it overflows.
Maximal skeleton path length is a bit different from YYMAXFILL:
it assumes that loops are iterated once (unlike YYMAXFILL calculation,
which disregards loops) and returns zero for empty regexp.

We need to know it in order:
    - to be sure it won't overflow
    - to store keys in a compact form (yet to be done)

This commit also makes DFA and skeleton store condition name and
source file line corresponding to current condition: it gets quite
annoying to pass these things around. This change caused another
change of test results (line numbers in error messages changed
for tests that use '-r' and reuse old DFA (don't reconstruct DFA
in 'use:re2c' blocks).
2015-09-09 22:43:31 +01:00
Ulya Trofimovich f742edb9b9 Fixed memleaks (skeleton nodes were not destructed properly).
Found with 'make vtests'
2015-09-09 16:26:28 +01:00
Ulya Trofimovich 4385e9d67f Make skeleton a part of DFA.
This let us create skeletom right after DFA creation (but befor DFA
has been mangled in different ways), but call skeleton methods any time.

Undefined control flow is now checked at the time of real code generation,
that's why all those tests that use '-r' changed: re2c stopped reporting
'rules:re2c' blocks and reports 'use:re2c' blocks instead.
2015-09-09 15:30:09 +01:00
Ulya Trofimovich 6e63459dda Suffixes of skeleton end nodes should be initialized by algorithm that uses them. 2015-09-09 13:09:25 +01:00
Ulya Trofimovich 32aa5bc846 Renamed function. 2015-09-08 17:57:06 +01:00
Ulya Trofimovich 5747320a21 A more logical way to update rules when constructing skeleton paths.
There's no need to keep rule one step behind path's arcs and update
it manually. Also, it is reasonable to set rule in constructor.
2015-09-08 17:33:34 +01:00
Ulya Trofimovich 19090ab7ce Reduced the time of path generation with '--skeleton'.
The algorithm now stores partially constructed paths in a compact
form and delays expansion until it reaches the end of current
branch of recursion. This has several advantages:
    - no need to store large structures in memory
    - write data to file in large chunks
    - path expansion is faster than step-by-step construction

Speedup is actually tenfold (but the way keys are dumped to file is
still not optimized and spoils benchmarks). Real speedup can be
observed on such files as:
    test/php20150211_zend_ini_scanner_trimmed.icF.re
, which cause ~5Gb dumps. Time has gone down: 8.5m -> 2.5m and will
be furter reduced to ~1m when key dumps are fixed. This will result
in generation speed ~20Mb/s which is quite good.
2015-09-08 15:14:09 +01:00
Ulya Trofimovich af65102144 Renamed and restructured various kinds of skeleton paths. 2015-09-08 12:06:52 +01:00
Ulya Trofimovich 56e684f200 Fixed eternal loop in path cover generation algorithm for '--skeleton'.
The simplest example I was able to come up with that reveals eternal
loop is the following:
    /*!re2c
        ( [^acf] | "0b" | "a"[^] | "a0"[^] )+ {}
    */
The problem was caused by my assumption that from any node there is
at least one non-looping path to end node. The assumption is true;
what I didn't take into account was that all such paths may go via
nodes that have already occured twice on the way to current node
(their loop counter is greater than 1). In this case the algorithm
would find no path to end node. Since not all prefixes would have
been covered (exactly none of them) the algorithm would loop forever.

Such branch may be abandoned safely: the algorithm will later find
another path to current state without loops.

As soon as I realized the problem the fix was trivial: if all outgoing
arcs have been exhausted and none of them yielded any results, abandon
current branch.
2015-09-07 09:30:06 +01:00
Ulya Trofimovich c17f717d21 With '--skeleton', store input data in binary form (rather than C/C++ code).
There's a limitation on the size of input files for C/C++ compiler and
the compiled binary will have to contain all that data (and thus may grow
very large).

Storing data in binary form and reading it from file dynamically is
the way it should be.
2015-09-05 09:39:28 +01:00
Ulya Trofimovich 0af40d147b With '-skeleton', dump data to file immediately as it is generated.
This way re2c won't consume memory even on large inputs.
2015-09-04 15:07:06 +01:00
Ulya Trofimovich c2fded35db Changed '.keys' file format (generated with '--skeleton').
Store length of strings instead of pointers to string start and end.

Storing pointers requires us to remember total length of strings already
written to file by the time we want to write next string. This is very
inconvenient if we want to dump strings as we perform DFS on graph:
we'll have to track size all the time (path-cover-generator already does
that, but all-paths-generator doesn't).

This adds a new local variable to the generated code ('token'), which
is used to backup cursor position when enterind DFA.
2015-09-03 15:18:45 +01:00
Ulya Trofimovich 0177fc4631 Split ".data" files (generated with '--skeleton') into two parts.
This is necessary to dump generated data as soon as possible instead
of keeping it until all data has been generated: we generate input
strings and keys simultaneously, but have to write all input strings
at once as one big string. Keys alone occupy lots of space, so
keeping only keys instead of keys and strings won't help.
2015-09-03 13:32:40 +01:00
Ulya Trofimovich a28d40048d Combined path cover generation with path cover size estimation.
We don't have any fallback algorithm in case path cover is too large.
We want to generate some paths anyway, so we have to construct path cover.
We shouldn't generate arbitrary large amounts of data.
2015-09-03 12:33:02 +01:00
Ulya Trofimovich ebcb82cb52 Omit some highly unlikely conditional exits from deep-first search.
With '--skeleton' re2c builds DFA skeleton and performs DFS in order to
estimate the size of data to be generated. It maintains size counter: as
soon as the counter reaches certain limit, DFS should stop.

Size counter is always checked when recursion returns.
Sometimes it is clear that size counter will overflow upon recursion
return (when arguments overflow already) and DFS can exit early (before
entering recursion).

This commit omits checks of some arguments (and correponding early exits
from DFS): first, path length is very unlikely to overflow (one has to
write/generate a regular expression with length of ~1Gb, in which case
skeleton generation won't be the worst problem); second, the number of
outgoing arcs in each vertex is also highly unlikely to exceed 1Gb limit.
2015-09-02 13:28:48 +01:00
Ulya Trofimovich 838d94f230 Split large source file into smaller files with distinct functionality. 2015-09-02 13:11:36 +01:00
Ulya Trofimovich c8851a91ec Narrowed the scope of ".data" file. 2015-09-02 12:39:47 +01:00
Ulya Trofimovich c6acd7ed99 Hid internals of skeleton paths under construction. 2015-09-02 11:44:25 +01:00
Ulya Trofimovich eb03931ac9 Renamed and fixed warning about undefined control flow in generated lexer.
Renamed '-Wnaked-default' to '-Wundefined-control-flow': the latter sounds
much scarier. :D

Completely changed the algorithm that is used to determine if default case
is not handled properly. Prior to this commit a simple and incorrent criterion
was used: whether there are code units that (alone) do not match any rule.
This gived false positives in cases like this:
    [^] [^] { rule }
here all code units meet the criterion: no single code unit matches a rule.
But obviously, default case is handled properly, because any input string
matches 'rule' (strictly speaking, any input string of length 2 or more, but
that's YYFILL's problem).

The new algorithm is more complex (in terms of time and space), yet it is
less heuristic: re2c parforms exhaustive deep-first-search on graph skeleton
and collects all bad paths.
2015-09-01 15:27:48 +01:00
Ulya Trofimovich b5441f2234 No need to NULL-terminate array of known size.
For some reason (which I yet do not understand) re2c uses size of DFA
state's "kernel" to determine whether a new state should be constructed
or some already constructed state (of the same "kernel" size) will do.

Since re2c knows "kernel" size for each state anyway, there's no need
to NULL-terminate "kernel" array while iterating over it: we can use
pre-calculated size instead.
2015-08-28 23:15:40 +01:00
Ulya Trofimovich 2c11437f90 Narrowed scope of local variables. 2015-08-28 23:10:33 +01:00
Ulya Trofimovich fa76747da9 Simplified array bounds check.
Comparing against pointer to the end of array is easier than calculating
array length, then setting next-to-last element to NULL and iterating
while not NULL.
2015-08-28 23:00:56 +01:00
Ulya Trofimovich c57c6f34ab Another minor simplification of control flow. 2015-08-28 22:33:51 +01:00
Ulya Trofimovich 85593a2323 Clarified control flow in nested loops. 2015-08-28 22:03:51 +01:00
Ulya Trofimovich ac4a55dbec Narrowed scope of local variables. 2015-08-28 21:52:28 +01:00
Ulya Trofimovich 7c6d02c056 Pass signed integer to 'std::setw' to avoid [-Wsign-conversion] warning. 2015-08-28 15:09:35 +01:00
Ulya Trofimovich 67d11d5bf7 Don't mix up empty code block with nonexistent one in rule actions.
Turns out that re2c allows empty code blocks:
    /*!re2c
    <a> "a" :=
    */

re2c up to 0.14.3 handled this correctly (generated empty action).
Since then this behaviour has been broken: re2c started to autogenerate
jump to nonexistent condition.
2015-08-27 23:30:03 +01:00
Ulya Trofimovich d9db976998 Delay '-Wcondition-order' reporting until we have necessary info.
'-Wcondition-order' depends on 'YYSETCONDITION' calls and 'types:re2c'
directive which may occur after condition dispatch is generated.
2015-08-27 14:03:26 +01:00
Ulya Trofimovich b47045247a Added warning '-Wcondition-order'.
See parent commit 8c1fe4f011
"Simplified tracking of condition order." for details.
2015-08-27 12:42:24 +01:00
Ulya Trofimovich 8c1fe4f011 Simplified tracking of condition order.
In theory re2c makes no guarantee about the order of conditions in
the generated lexer. Users should use 'YYGETCONDITION'/'YYSETCONDITION'
interface and generate enum with condition names using either '-t'
option or '/*!types:re2c*/' directive. Only members of the generated
enum should be used with 'YYGETCONDITION' and 'YYSETCONDITION'.
This way code is independent of internal re2c condition numbering.

However, it turns out that some users (and notably, PHP) rely on
internal condition numbering: they manually hardcode condition numbers
and make re2c generate condition dispatch in such a way that it
doesn't mention condition names at all (e.g. with in the form of nested
'if' statements with '-b' or in the form of 'goto' table with '-g').
The code compiles, but change of code generation mode may break
compilation. Even worse, change of internal re2c condition numbering
may lead to epic runtime failures.

So re2c cannot just change internal condition numbering: it has to
preserve the existing numbering scheme (rather illogical and not
alphabetically sorted).

This commit tries to simplify tracking of condition numbers.
2015-08-26 12:41:48 +01:00
Ulya Trofimovich ef3502b09c Fixed bug #119: "-f with -b/-g generates incorrect dispatch on fill labels".
Consider the following example 1.re:
    /*!re2c
        "" {}
    */
With -if, re2c would generate correct dispatch:
    $ re2c -if 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:41:45 2015 */
            switch (YYGETSTATE()) {
            default: goto yy0;
            case 0: goto yyFillLabel0;
            }
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}

With -bif all positive YYGETSTATE() values will lead to yyFillLabel0,
which is clearly an error: values that are greater than 0 should lead
to yy0:
    $ re2c -bif 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:40:32 2015 */
            if (YYGETSTATE() < 0) {
                    goto yy0;
            } else {
                    goto yyFillLabel0;
            }
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}

With -gif the error is different: all values greater than 0 now cause
undefined behaviour (access to memory not within array bounds):
    $ re2c -gif 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:47:41 2015 */
    {
            static void *yystable[] = {
                    &&yyFillLabel0,
            };
            if (YYGETSTATE() < 0) {
                    goto yy0;
            }
            goto *yystable[YYGETSTATE()];
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}
    }

The situation gets even more tricky with re2c:state:abort configuration.
Besides, YYGETSTATE() macro is called multiple times with -b and -g,
which is not so good. Additional checks with -g don't help gain performance
either.

Fix: always generate simple switch.
2015-08-25 11:33:29 +01:00
Ulya Trofimovich f4c0ad80a6 Makefile.am: update bootstrap parser when necessary.
The mechanism of updating bootstrap parser was broken by commit
b2bc24704e : "Support 'make distcheck'."

Before that commit bootstrap parser was updated every time when autogenerated
parser was updated. This approach contradicted with 'make distcheck' which
mounts top source directory read-only (including bootstrap files). That commit
tried to solve the problem by checking if the autogenerated parser has changed
and only then copying it to bootstrap parser.

I made two mistakes:
    - philisophic mistake: autogenerated parser was actually altered by
      'make distcheck' because of altered paths in '#line' info;
    - shell scripting mistake: the check if the autogenerated parser has
      changed was inverted, so bootstrap parser was never updated;

This commit makes use of two observations:
    - bootstrap parser depends on the source parser, not on the autogenerated
      parser;
    - bootstrap parser shouldn't at all contain line information: at the time
      it is copied to build directory the relative path from build directory
      to source directory may be completely different (as it is with 'make
      distcheck');
2015-08-24 14:44:18 +01:00
Ulya Trofimovich fa7659cb67 distcheck.sh can only run from top source directory. 2015-08-24 13:23:55 +01:00
Ulya Trofimovich 3732f5f279 Explicit cast of signed nonnegative to unsigned (found with [-Wsign-conversion]). 2015-08-24 10:59:44 +01:00
Ulya Trofimovich 7bed1b9631 Parse configuration strings in the same way as character strings and classes.
re2c allows configuration strings to contain escape sequencs as long
as the escaped code points fit into 1-byte range.

Finally both 'Scanner::unescape' functions can be removed along with
a whole bunch of [-Wsign-conversion] warnings. :)
2015-08-23 11:34:13 +01:00
Ulya Trofimovich 33fe08f88d Tests: simple tests for parsing inplace configurations.
Tests do not ensure that configurations are handled correctly or
have any impact on re2c behaviour. They only ensure that these
configuration names are recognized as valid.
2015-08-22 15:52:27 +01:00
Ulya Trofimovich 8fdb9c7498 Parse inplace configuration names in lexer.
Make re2c do all the dirty work instead of barely recognizing
configuration-like lexeme and manually matching the lexeme against
all allowed configuration names.

This commit adds many new tokens, which means that re2c-generated lexer
and bison-generated parser have both become larger. The difference
is not as great as one might expect: ~60 Kb -> ~80 Kb in both cases.
2015-08-22 14:49:17 +01:00
Ulya Trofimovich c73800f114 Zero-extend code units when casing them from 'signed char' to 'uint32_t'.
The problem starts with lexer: it should operate on unsigned chars
(as re2c wants). Then these casts won't be needed at all. Mixing
signed and unsigned chars is bad and lexer should be rewritten to
use unsigned chars.
2015-08-20 13:24:42 +01:00
Ulya Trofimovich e8abc1ef05 Forbid newline in strings and character classes.
Like C language, re2c allows all characters of current charset excapt for
newline and backslash to apper unescaped in string and class literals.

Added tests:
    - all possible characters in strings and classes (omitting
      newline, escaping backslash and quotes/closing bracket)
      with different encodings (re2c up to 0.14.x would segfault
      on this test with '-u' and '-w')
    - string with newline
    - string with unescaped backslash followed by newline (so that
      it won't stick to next character)
2015-08-20 13:05:07 +01:00
Ulya Trofimovich 59dc472c81 Tests: code points that exceed maximum for current encoding.
Test changes introduced by commit 0346d1666f:
"Check if code point exceeds maximum. Correctly cast 'char' to 'uint32_t'."
2015-08-20 12:35:47 +01:00
Ulya Trofimovich 0346d1666f Check if code point exceeds maximum. Correctly cast 'char' to 'uint32_t'.
First fix:
re2c used to check if code point exceeds maximal value for current
encoding when parsing it. When I moved parsing code points to lexer
I forgot the check.

Second fix:
I assumed that 'static_cast<uint32_t>' on 'signed char' zero-extends.
But I was wrong: it sign-extends. Need to cast to 'unsigned char'
instead.
2015-08-20 12:09:52 +01:00
Ulya Trofimovich cd4c7d830b Parse unquoted flex-like strings in lexer.
Such strings can only contain ASCII letters, digits and uderscore:
no escapes. So there's very little parsing to do: just map code units
directly to code points.
2015-08-19 18:49:28 +01:00
Ulya Trofimovich 0d316a3794 Parse character strings in lexer.
This commit is a continuation of e42f271e4b:
"Parse character classes in lexer." It makes lexer parse individual code
points instead of barely recognizing string of code points.

Since the contents of case sensitive strings, case insensitive strings
and character classes are lexically the same (except for escaped quotes
or closing bracket), we can parse them all in the same lexer block.

Note that re2c allows any 1-byte code points. Maybe we should report
non-ASCII or non-printables.
2015-08-19 18:31:04 +01:00
Ulya Trofimovich 075cb7ee1e Removed unused function. 2015-08-18 22:11:58 +01:00
Ulya Trofimovich e0499d0629 Added warning '-Wuseless-escape'.
This is to warn about escaped printable ASCII characters that
shouldn't be escaped in the current context (e.g. quotes inside of
a character class).
2015-08-18 21:57:32 +01:00
Ulya Trofimovich 926bcc4bf9 Added warning '-Wswapped-range'.
When re2c parses character class and finds a range with lower bound
greater than upper bound, it silently swaps bounds. Warn about such
cases.
2015-08-18 17:14:45 +01:00
Ulya Trofimovich e42f271e4b Parse character classes in lexer.
Before this commit, lexer would barely recognize class as a whole
lexeme and pass it to functions that would further parse is by manually
picking individual code points and control characters out of the lexeme.

Heh, re2c is made for such kind of stuff (and it does it much better).
So now lexer parses individual code points or control characters and
stores them as a sequence of code points. Then an outer function
splits this sequence into ranges and individual characters.

I tried to preserve existing behaviour (judging from test suite only
the text of some error messages has changed). Added some autogenerated
tests (and the generator script itself), but these tests are not exhaustive.
2015-08-18 15:54:22 +01:00
Ulya Trofimovich 6d3c3f4651 Lexer: no need to have "{0,}" special case.
Now "{0,}" is handled by general case for counted repetition. Had to
fix test because of swapped alternatives in construction of regexps
of the form "r*" and "r{n,".

Added some tests for counted repetition.
2015-08-16 20:57:29 +01:00
Ulya Trofimovich 030952a220 Restored explicit cast that was removed in 7af5d437e4.
Found with [-Wsign-compare] while building with MINGW: pointer
difference is of different size on linux and windows.
2015-08-16 20:14:50 +01:00
Ulya Trofimovich 9f6a3f0282 Force definition of some conditionally defined parts of <stdint.h>.
Got some errors about undefined 'UINT32_MAX' and others while trying
to build re2c with MINGW. These variables are defined conditionally in
<stdint.h> depending on the following defines:
    __STDC_LIMIT_MACROS
    __STDC_CONSTANT_MACROS
Fix: defined these symbols in the beginning of "src/util/c99_stdint.h".

Also found out that "src/util/c99_stdint.h" didn't compile in the
absense of system <stdint.h> (which is exactly the case when it was
written for). THe problem was caused by incorrect use of 'typedef'
statement; fixed easily. What a shame I didn't compile it before ;D
2015-08-16 20:02:04 +01:00
Ulya Trofimovich 06a2fe5070 Fixed [-Wsign-conversion] warnings in 'testrange' sources. 2015-08-16 15:21:23 +01:00
Ulya Trofimovich 819c85733a Use custom function instead of 'atoi' to read 32-bit integers.
Using 'atoi' displeased me for several reasons:
    - 'atoi' doesn't check for overflow
    - by the time 'atoi' was called, re2c has already parsed input
      string and knows that it is well-formed, no need to do it twice
    - atoi returns 'int', custom function allows to refine types and
      avoid casts between signed/unsigned values or [-Wsign-conversion]
      warnings

Added test for new conversion functions.
2015-08-16 12:08:21 +01:00
Ulya Trofimovich 06e8505014 Don't use special regexp type for counted repetitions.
Counted repetitions are regexps of the form:
    r{n}
    r{n,m}
    r{n,}

They can be expressed in terms of concatenation, alternation and
iteration:
    r{0}      <empty regexp>
    r{n}      r{n-1} r
    r{n,m}    r{n} (r{0} | ... | r{m-n})
    r{n,}     r{n} r*

Reducing special regexp type to represent counted repetitions allows
us substitute complex code that compiles them to bytecode instructions
with simpler code that constructs counted repetitions using concatenation,
alternation and iteration.
2015-08-15 17:42:41 +01:00
Ulya Trofimovich a148131156 Removed unused struct field. 2015-08-15 16:22:28 +01:00
Ulya Trofimovich 180bd00fe6 Store lexer buffer size inside of lexer class. 2015-08-14 14:37:12 +01:00
Ulya Trofimovich 286f8990e8 Some more explicit casts in lexer fill procedure (found with [-Wsign-conversion]).
Lexer tries to maintain certain layout of pointers to buffer.
Buffer refilling procedure relies on that layout.
2015-08-14 14:36:09 +01:00
Ulya Trofimovich 48c067251c Lexer: unified token length calculation.
Token length equals the difference between two pointers: YYCURSOR
value on the moment of successful match and YYCURSOR value when
entering DFA. This difference should be nonnegative and fit buffer
size.
2015-08-14 13:57:58 +01:00
Ulya Trofimovich 7af5d437e4 Use different local variables for unrelated tasks. 2015-08-14 13:57:31 +01:00
Ulya Trofimovich d1c414cebb Fixed '#27 re2c crashes reading files containing %{ %}' (patch by Rui)
merged commit b068f3ad2e from master.
2015-08-12 22:32:24 +01:00
Ulya Trofimovich 172803accd Lexer: reduced unnecessary macro. 2015-08-12 18:50:38 +01:00
Ulya Trofimovich 4fcbf6db3e Lexer: glued together two variables with almost identical functionality.
These two variables ('ScannerState' class member 'cur' and local variable
'cursor') both played the role of YYCURSOR: YYCURSOR was defined to
'cursor', but the code had to adjust 'cur' to 'cursor' on every return
and restore it when reentering lexing procedures.

There was only two obscure places in which they were not completely
syncronized. Both looked the same:

    cur = ptr > tok ? ptr - 1 : cursor;

However, 'ptr' is effectively YYMARKER and is never changed manually
by lexing procedures; 'tok' should point to the beginning of current
lexeme; this check doesn't make sense to me. This is an attempt to
resume lexing one character before YYMARKER, but what for? YYMARKER
isn't even used in Scanner::scan (look at the the generated code),
so 'ptr > tok' is always false.

This check is present since the initial commit, so I cannot trace back
it's origin.

As it doesn't break any tests I hereby simply remove it.
2015-08-12 18:42:17 +01:00
Ulya Trofimovich 79411974da Added tests for occasionally fixed bug in code generation.
The bug was triggered by the following conditions: '-b'
(or any flag that implies '-b') and encoding with code units
wider than 1 byte (that is, UTF-16, UTF-32 and UCS-2).

The bug itself: re2c omitted 'goto <some state>;' when it
should have been generated. The absense of goto caused incorrect
control flow. One cas verify it in two ways using the minimal test
added by this commit:
    - manually compare the code generated before and after fix
      and ensure that newer version generates correct code;
    - run the test with --skeleton, then try to add/remove
      the goto statement, compile and run: the code without
      goto will fail, the code with goto will not;

git-bisected commit which fixed bug:
    commit e42003d805
    Author: Ulya Trofimovich <skvadrik@gmail.com>
    Date:   Wed Mar 11 12:46:58 2015 +0000

        Pass limited span instead of checking range all the time.

Also gound commit that introduced bug:
    commit d10fb601f3
    Author: helly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
    Date:   Fri Dec 30 16:24:07 2005 +0000

        - Allow to use -w with -b
        # Still quite some work to do but it is possible
2015-08-12 13:52:57 +01:00
Ulya Trofimovich 5bbd0819e6 More accurate loop counting (inspired by [-Wsign-compare]). 2015-08-11 18:52:41 +01:00
Ulya Trofimovich 4686a097aa Loop counter should be unsigned (found with [-Wsign-compare]). 2015-08-11 17:44:29 +01:00
Ulya Trofimovich 46bf121eb9 Simplified regexp construction for case insensitive strings.
As for now, we only support ASCII. This should be fixed.
2015-08-11 17:36:29 +01:00
Ulya Trofimovich 1ba85989cf Explicit cast of 'char' to 'unsigned char' in cmd options lexer.
Much the same as previous commit, only this time YYCTYPE has been
erroneously set to 'char' instead of 'unsigned char. It didn't
cause any warnings or errors becase regular expressions contain
only ASCII range characters. However, relying on this is unsafe:
hypotheticlly re2c can generate some strange comparisons that compile
but fail in runtime.

Explicit cast makes sure thet all comparisons are between unsigned
values.
2015-08-11 15:18:04 +01:00
Ulya Trofimovich b5b2562ebe Explicit cast of 'char' to 'unsigned char' in lexer.
Source code is in ASCII: pointers have type 'char *', but re2c
makes an implicit assumption that YYCTYPE is unsigned when it
generates comparisons.

At first glance making YYCTYPE 'char' instead of 'unsigned char'
seems to fix the problem (no more warnings). But it's only because
re2c-generated lexer happens to make no comparisons with constants
larget than 0x7F. Lexer rules may change a bit and then we'll have
lots of warnings about 'comparison between signed and unsigned
values' and 'case label exceeds maximal value for type', not
mentioning that it may lead to real errors.

Explicit cast makes sure thet all comparisons are between unsigned
values.
2015-08-11 14:38:34 +01:00
Ulya Trofimovich a0fe9a0579 Simplified pretty-printing individual characters. 2015-08-11 11:12:32 +01:00
Ulya Trofimovich 8603fa80d3 run_tests.sh: a minor tweak to speed up tests (a little). 2015-08-11 11:06:09 +01:00
Ulya Trofimovich d6379090ff A better way to avoid GCC [-Wreturn-type] false positives.
Though all enum values are handled in switch, GCC still complains
that 'control reaches end of non-void function'. Adding default
clause helps and it's better than returning some spurious constant.
2015-08-10 17:11:01 +01:00
Ulya Trofimovich b7132f3992 configure.ac: added warning to CXXFLAGS: -Wsign-conversion 2015-08-10 13:49:42 +01:00
Ulya Trofimovich 82d3d8aee8 Makefile.am: dropped bison flags: -y -d --no-lines.
-y stands for yacc compatibility, we don't need it since we no longer
accept yacc instead of bison.

-d stands for defines file, we already specify that in makefile rule
for parser.

--no-lines is generally useless and didn't have any effect for some
reason (#line directives are present).
2015-08-10 13:39:57 +01:00
Ulya Trofimovich c61a7dd523 run_tests.sh: separate stdout and stderr, diff with -b on wine.
Found some errors while testing mingw-built re2c.exe on wine:
    1. redirecting stderr to stdout resulted resulted in random
       mix in tests that triggered re2c warnings
    2. removing all '\r' symbols in the generated files didn't
       work anymore since some tests that contain '\r' were added

Fixed:
    1. redirect both to different files and cat manually
    2. diff with -b flag on wine
2015-08-10 13:16:56 +01:00
Ulya Trofimovich 87c0846622 Stop loosing arcs in DFA loops when building path cover with --skeleton.
The problem with the algorithm was that when one and the same skeleton
node is visited for the 3rd time, the algorithm would abandon this
branch and drop all the path prefixes that lead to it. It's ok when
bruteforcing all paths (the arcs in the dropped prefixes will occur in
other paths that lead to final states), but it's not ok for path cover:
some arcs may have occured only in these dropped prefixes).

The fix is easy: just check if the branch was cancelled and in case it
was try the same prefixes with another branch.

This small example demonstrates the problem:

    /*!re2c
        [^\x00]* [\x00] {}
    */

DFA skeleton looks like this:

    state 0:
        arcs to state 0: [0x01, 0xFF]
        arcs to state 1: [0x00]
    state 1: final

Before the fix, re2c would generate the following paths (provided
path cover construction is forced instead of generating all paths):

    - 0x01,0x00
    - 0x00

Clearly the [0xFF] arc looping from state 0 to state 0 is missing
(uncovered). After the fix:

    - 0x01,0x00
    - 0xFF,0x01,0x00
    - 0x01,0xFF,0x00
    - 0x00

Not a minimal path cover, but we don't need it. We just need a small
enough one.
2015-08-10 12:03:07 +01:00
Ulya Trofimovich f5e9045c3f Yet one more explicit cast of pointer difference to uint32_t.
Much the same as previous commit: array of length bounded with 32 bits,
first pointer points to some random element. second pointer points to
the beginning of array (unless there were some errors in calculatins
that would have likely crashed re2c anyway).

Fixes [-Wconversion] warning.
2015-08-10 11:48:46 +01:00
Ulya Trofimovich 75c3a63b59 Yet another explicit cast of pointer difference to uint32_t.
This time we deal with pointers in 'Ins' array (the length of array
equals the calculated size of regular expression, which is currently
of type uint32_t: larger regular expressions will surely crash re2c).

So we can guarantee that, if regexp was correctly compiled to instructions,
than the first pointer points to some instuction in the array and second
pointer points to the beginning of array, so this cast is safe.

If compilation was incorrect than re2c will fail anyway.

Fixes [-Wconversion] warning.
2015-08-10 11:41:51 +01:00
Ulya Trofimovich ce7e9d37b3 Another explicit cast of pointer difference to uint32_t that seems to be safe.
In theory, 'top' points at the top of stack and it's value is always greater
than or equal to 'stk' that points to stack bottom. Total stack size is
equal to 'DFA::nStates', which is of type uint32_t (DFAs larger than
2^32 states are currently not supported an will crash re2c).

In practice, 'stk' is not changed and 'top' is only incremented
before the cast (it's decremented afterwards. Note that the function
is self-recursive).

Fixes [-Wconversion] warning.
2015-08-10 11:25:05 +01:00
Ulya Trofimovich 46c5baeae0 Explicit cast of pointer difference to uint32_t: it seems to be safe from the code.
In theory, this function returns the number of 'Span's in the newly
constructed 'Span' array, so it must be a non-negative integer number
that fits into 32 bits and the cast is safe.

In practice, 'x0' variable stays unchanged in this function, while
'x' variable's value can only increase: whenever it can be (conditionally)
decremented, it is always unconditionally incremented. So 'x - x0'
must be non-negative.

Fixes [-Wconversion] warning.
2015-08-10 10:44:42 +01:00
Ulya Trofimovich 09fde6595a Print single character as char rather than convert it to one-symbol string. 2015-08-10 10:26:14 +01:00
Ulya Trofimovich b463ce94b8 Fixes some hidden NULL pointer dereferencing.
'specMap' parameter can sometimes be NULL (when not in '-c' mode).
In code it was dereferenced before the check for '-c', but due to
compiler optimizations this was never revealed.

I found the bug while trying to measure the size of 'specMap'
before the check (caught segfault). Fixed by moving the check prior
to dereferencing.
2015-08-10 10:19:00 +01:00
Ulya Trofimovich 120df2f2b9 Explicit cast of pointer difference to uint32_t: it's obviously safe from the code.
Fixes some [-Wconversion] warnings.
2015-08-10 10:12:20 +01:00
Ulya Trofimovich d1dd093cf3 'DFA::kCount' type should be ptrdiff_t as it's involved in pointer arithmetics. 2015-08-10 10:07:23 +01:00
Ulya Trofimovich 98dc7e4a28 Allow generic container to have size_t elements rather than uint32_t.
Cast to uint32_t in those use cases when we are sure that container
only contains some few elements.
2015-08-10 09:58:10 +01:00
Ulya Trofimovich f9fbcdde7b Use 32 bits insted of 8 for warning status.
Warning status can be in fact represented with only 2 bits, but
since it's engaged in arithmetic operations it gets promoted and
special precautions are needed. Much easier to ure 32 bits:
warnings are nowhere near performance/memory bottleneck.
2015-08-09 20:31:00 +01:00
Ulya Trofimovich 3cfd4acd14 Use ptrdiff_t instead of uint32_t to represent offset in buffer.
Found with [-Wconversion].
2015-08-09 20:27:10 +01:00
Ulya Trofimovich d55a4460f1 Removed useless piece of code (pretty-printing octal characters).
This piece of code could (and should) never be executed: EBCDIC and
non-pritables are handled prior to calling 'prtCh'.
2015-08-09 20:11:20 +01:00
Ulya Trofimovich 4114fe90f6 Use size_t to store the length of path in skeleton.
Though this length shouldn't actually excedd 32 bits (othewise
too much data will be generated, and that is checked), it's better
to use size_t and don't care about the order of checks.
2015-08-09 20:01:52 +01:00
Ulya Trofimovich 8b235647dc Added comment. 2015-08-09 20:01:17 +01:00
Ulya Trofimovich 105757021b A special truncated unsigned 32-bit type for overflow-sensitive calculations.
With --skeleton switch we need to generate lots of data: strings that
correspond to various paths in DFA and match given regular expression.
For small graphs we can afford to generate all paths, for large graphs
we can only generate path cover. Anyway we need to be able to estimate
the amount of data to be generated (measured in skeleton arcs). Since
it can easily exceed 32 bits (and 64 as well), calculations must stop
as soon as certain limit is reached.
2015-08-09 20:00:20 +01:00
Ulya Trofimovich e71aedbee4 Encodings: use 32-bit unsigned arithmetics instead of 8-bit and 16-bit.
8-bit and 16-bit unsigned integers used in arithmetic operations
are promoted to 32 bits before operation and then truncated back.
Theoretically this may change their value.

This fixes a lot of [-Wconversion] warnings.
2015-08-09 19:07:10 +01:00
Ulya Trofimovich 7562ce7493 configure.ac: added warning to CXXFLAGS: -Wconversion 2015-08-09 19:01:00 +01:00
Ulya Trofimovich a6b8f7c643 Makefile.am: dropped re2c flag '-i'.
Line information is useful.
2015-08-06 12:04:21 +01:00
Ulya Trofimovich fdc3a0df24 Forgot to update bootstrap lexer (changed by commit 1d4462d5d5). 2015-08-06 10:57:46 +01:00
Ulya Trofimovich 58d151e702 Now -Werror-<warning> turns on <warning> (unlike -Werror in general).
At least GCC does so.
2015-08-05 10:33:55 +01:00
Ulya Trofimovich 1d4462d5d5 Better representation for rule actions; omit line info for autogenerated actions.
Since there's no such code in source file, there's no sense in
pointing into it. Updated test.
2015-08-04 13:38:57 +01:00
Ulya Trofimovich 6bfa100ffc Free memory allocated for range suffies at the same time as everything else.
Moved static member definition closer to class.
2015-08-04 11:36:13 +01:00
Ulya Trofimovich 32feb0eaf3 Added simple struct to store locations of parsed elements in source file. 2015-08-04 11:10:54 +01:00
Ulya Trofimovich 0c09cf94a6 New condition belongs to the whole rule rather than to rule's code. 2015-08-04 10:29:47 +01:00
Ulya Trofimovich f02474d74d Removed unused 'strdup' function and autoconf check.
Function left unused by commit 00b14f309b.
2015-08-04 09:53:52 +01:00
Ulya Trofimovich bd2875441c Some tests for windows-style newlines (CR LF).
Copied two existing large tests and patched newlines: LF -> CR LF.
2015-07-30 23:10:58 +01:00
Ulya Trofimovich e02b761a74 Fixed bug #115 "flex-style named definitions cause ambiguity in re2c grammar".
This commit removes 10 shift/reduce conflicts in bison grammar for re2c.
These conflicts are caused by allowing flex-style named definitions
    name regular-expression
to contain newlines and to be mixed with rules. It's not just some
conflicts in LALR(1) grammar, it is genuine ambiguity as can be observed
from the following example:
    /*!re2c
        name "a"
        "b" "c" {}
    */
which can be parsed in two ways:
    definition -> name "a"
    rule -> "b" "c" {}
and
    definition -> name "a" "b"
    rule -> "c" {}
, both ways being perfectly valid.

This commit resolves ambiguity by forbidding newlines in flex-style
named definitions (conforming to flex syntax). Newline in these
definitions is treated in a special way: lexer emits token 'FID_END',
which marks the end of flex-style named definition in parser.
2015-07-30 15:11:03 +01:00
Ulya Trofimovich c8c8426f13 Fixed segfault on options that expect an argument but are passed none.
Example of commands that triggered segfault:
    $ re2c -o
    $ re2c --type-header
    $ re2c --input
2015-07-29 14:46:19 +01:00
Ulya Trofimovich 92a6743b7b Force custom input API with "--skeleton" option.
Dropped this line while rewriting options parser.
2015-07-29 12:54:50 +01:00
Ulya Trofimovich c42303423a Removed extra newline at the end of some error messages. 2015-07-29 12:37:51 +01:00
Ulya Trofimovich dd0ddef537 Output error message when passed multiple arguments after "--" option.
All arguments after "--" are treated as input files, but re2c expects
exactly one input file.
2015-07-29 12:32:20 +01:00
Ulya Trofimovich 9c9e951b1c Commented parser conflict.
See https://github.com/skvadrik/re2c/issues/115

orts the commit.
2015-07-29 12:19:40 +01:00
Ulya Trofimovich 64c030b8e5 Improved warning messages with '-Werror'.
Report an error rather than a warning (at least GCC does so).
2015-07-27 21:29:03 +01:00
Ulya Trofimovich 82be0ddb39 Output condition name with '-Wnaked-default' in '-c' mode. 2015-07-27 15:54:57 +01:00
Ulya Trofimovich c0938ded1a Updated tests.
Line info changed in warning messages since commit
929c87fdf3:
"Unified location output in warning messages.
2015-07-27 15:33:29 +01:00
Ulya Trofimovich 929c87fdf3 Unified location output in warning messages. 2015-07-27 15:12:49 +01:00
Ulya Trofimovich 731b54a7d7 Renames '-Wempty-rule' -> '-Wmatch-empty-string' and improved message. 2015-07-27 12:57:46 +01:00
Ulya Trofimovich 0cc218a758 Enable warnings globally for tests.
Fixed reference results for tests that trigger warnings.
2015-07-27 12:45:36 +01:00
Ulya Trofimovich 15111a168c Don't lose stdout and stderr when testing with -o. 2015-07-27 11:45:30 +01:00
Ulya Trofimovich b7053a4aed Don't output generated code when failed with -Werror. 2015-07-27 11:41:23 +01:00
Ulya Trofimovich ceafc79c5c Added warinigs: -W, -Werror.
-W: enable all warnings
    -Werror: turn all enabled (hereafter) warnings into errors

Specific warnings added by this commit:
    -Wempty-character-class
    -Wempty-rule
    -Wnaked-default

For each warning there are -Wno-, -Werror-, -Wno-error- options.
2015-07-27 09:00:33 +01:00
Ulya Trofimovich c4d1ca6d46 Fixed typos in release script, updated release guidelines. 2015-07-24 20:28:20 +01:00
Ulya Trofimovich f9b2c6b887 Split release script into tw parts: distcheck and everything else. 2015-07-21 19:06:07 +01:00
Ulya Trofimovich a89506bd1f Makefile.am: remved nonexistent file 'doc/index.html'. 2015-07-21 18:17:54 +01:00
Ulya Trofimovich 38bf91452e Site front page 'doc/index.html' gone to branch 'gh-pages'.
Note that anther site page, manual.html, is autogenerated from
'doc/re2c.ad.in' which is also used to generate documentation.
2015-07-21 17:46:09 +01:00
Ulya Trofimovich f323e50091 Makefile.am: added forgotten header. 2015-07-21 17:22:11 +01:00
Ulya Trofimovich ef1e93bc8a Fixed re2c behaviour with "--" command line option.
All arguments after "--" are treated as non-options. This can be
used to handle option-like filenames (those starting with "-" and "--").
2015-07-21 13:47:31 +01:00
Ulya Trofimovich d1d247b003 Allow to specify exacly one input file and at most one output and header file. 2015-07-21 12:15:01 +01:00
Ulya Trofimovich 9390563c12 Fixed GXX warning '-Wsuggest-attribute=format'.
g++ warns if function with '__attribute__((format (printf, ...)))'
has wrong number of arguments or argument type is wrong.
2015-07-20 22:14:12 +01:00
Ulya Trofimovich 4c97337734 Use 'vfprintf' instead of 'fprintf' to print variadic arguments.
Added GCC warninigs -Wformat=2 (reveals this error) and
-Wsuggest-attribute=format.
2015-07-20 19:45:54 +01:00
Ulya Trofimovich 63c488515f Modified release script to try build with bmake as well as make. 2015-07-20 15:37:05 +01:00
Ulya Trofimovich 66ade3d86b Makefile.am: drop non-POSIX make feature: '$<' in target rules.
POSIX make allows '$<' only in inferencee rule.
Found while trying to build with bmake.
2015-07-20 15:24:46 +01:00
Ulya Trofimovich 71f48b844c Makefile.am: respect various 'make' alternatives: use '$(MAKE)'. 2015-07-20 14:42:32 +01:00
Ulya Trofimovich f4e1f6b1de Makefile.am: use inference rule '.re.cc' to avoid rule duplication.
Inference rules is a standard POSIX make feature.
2015-07-20 14:39:54 +01:00
Ulya Trofimovich 5b6e57cf2a New re2c-based parser for command line options. 2015-07-19 15:22:47 +01:00
Ulya Trofimovich 9d2ff171f8 Removed unused class variable. 2015-06-29 21:51:02 +01:00
Ulya Trofimovich 7f88d07ef6 Don't check range bounds in pretty-printing function. 2015-06-26 14:09:51 +01:00
Ulya Trofimovich 20ea94a3dc Removed unused function. 2015-06-26 14:01:56 +01:00
Ulya Trofimovich 8aa4db21bd Comment on test for character class operations. 2015-06-23 22:02:27 +01:00
Ulya Trofimovich 6dbe52d05d Added test for operations on character classes (addition and subtraction).
Test is built into a separate binary. Both test building and running
is triggered by `make check`.
2015-06-23 21:44:13 +01:00
Ulya Trofimovich 3e939ded3f Operations on character classes: fixed subtraction, simplified addition.
Subtraction was broken by commit f56196d29f:
"Simplified implementation of range union and difference."
2015-06-22 13:50:17 +01:00
Ulya Trofimovich e6827f0332 More tests for "--empty-class" option.
This time I found all tests that are affected by this option
(that is, contain empty ranges) and added explicit option variants
for most of them (excluding 'test/empty_range.*' group, as we already
have 'test/bug61_positive.*' group that checks the same thing).
2015-06-16 16:09:32 +01:00
Ulya Trofimovich 42f09d9d2d Updated docs (added new options an long variants for all options). 2015-06-16 15:48:55 +01:00
Ulya Trofimovich 5d075c49f1 Makefile.am: added forgotten header. 2015-06-16 15:20:02 +01:00
Ulya Trofimovich 5cdb7a1af4 Added cmd option "--empty-class <match-empty|match-none|error>".
This option controls re2c actions when it encounters empty character
class (e.g. [], [^\0x00-\xFF] or [\0x00-\xFF]\[\0x00-\xFF]):
    match-empty (default) - match on empty input
    match-none - fail to match on any input
    error - compilation error

This is a final fix for bug #61 "empty character class [] matches empty string".
2015-06-16 14:17:17 +01:00
Ulya Trofimovich 7157354c45 Partial fix for bug #61 "empty character class [] matches empty string".
Given the following code:
    /*!re2c
        [] {}
    */

    /*!re2c
        [^\x00-\xFF] {}
    */

    /*!re2c
        [\x00-\xFF]\[\x00-\xFF] {}
    */
re2c versions <=0.13.6 and >=0.13.7 behaved differently.
0.13.6 consistently considered that empty range should match empty string.
Since 0.13.7 empty positive range [] and empty difference (e.g. [a-z][a-z])
still match empty string, but empty negative range (e.g. [^\x00-\xFF])
matches nothing (always fails). The faulty commit is
28ee7c95bc
"Added UTF-8 encoding support and tests for it."

This commit brings back consistent behaviour of 0.13.6: empty range,
however it was constructed, always matches empty string. Whether this
behaviour is sane or not is another question.
2015-06-16 12:19:03 +01:00
Ulya Trofimovich 50802e4696 Construct non-NULL regexps from NULL ranges (for variable-length encodings).
NULL range represents empty range: range union and difference functions
return NULL for empty ranges. Thus NULL can be passed to functions
that construct regexp from range ('MatchOp', 'UTF8Range' and 'UTF16Range').
All these functions must behave return non-NULL for NULL ranges, since
further code relies on this.
2015-06-15 15:39:29 +01:00
Ulya Trofimovich 1ecdfb66f4 Crash on attempt to create range with lower bound greater or equal to lower bound.
Better have an assert than nothing until we handle such cases properly.
As for now, if the user inputs range like [9-0], it will be tranformed
to [0-9]. Later re2c should at least warn about such cases.
2015-06-15 15:09:02 +01:00
Ulya Trofimovich a4c87b8fc6 Now range internals are only visible to union/difference functions.
Ranges must be constructed so that linked ranges don't overlap and
are monotonous. This is always true for one-link ranges created by
range constructor, and we construct larger ranges from them using
union and difference functions (that maintain the invariant).
2015-06-15 14:31:26 +01:00
Ulya Trofimovich f56196d29f Simplified implementation of range union and difference. 2015-06-15 14:09:08 +01:00
Ulya Trofimovich 2515872e68 Explicitly shallow-copy ranges instead of using obscure copy constructor. 2015-06-13 11:51:19 +01:00
Ulya Trofimovich 66babb646b Restructured sources layout, improved formatting. 2015-06-10 17:30:15 +01:00
Ulya Trofimovich 13162cd582 Unified macro names in header guards.
Inspired by sudden collision with '__COUNTER__' I occasionally got
while guarding 'src/util/counter.h'.

Now all headers use guards of the form '_RE2C_PATH_TO_HEADER_BASENAME_'.
Some compilers (e.g. clang++) would warn about [-Wreserved-id-macro],
but their reasonong about reserved macro names is quite crude and re2c
is not able to confirm their standards anyway (e.g. autoconf-generated
macro name 'SIZEOF___INT64').
2015-06-09 17:36:36 +01:00
Ulya Trofimovich d2ca05e003 Distinct restricted type for rule priority.
As with labels, try to control how rule priorities are created:
make a special counter that creates new priorities and disallow
everyone but this counter do it.
2015-06-09 15:28:58 +01:00
Ulya Trofimovich 7cea510965 Simplified creation of rule states and backup states.
New simpler implementation uses STL containers instaed of sparse
array. It's less efficient, but the place is not a bottleneck and
simplicity is more important than efficiency.
2015-06-08 22:25:32 +01:00
Ulya Trofimovich 7bb605ea77 A better data structure for mapping 'yyaccept' values to DFA rule states.
'yyaccept' values must be continuous natural numbers starting from 0,
so array indices represent them ideally.
2015-06-08 15:06:56 +01:00
Ulya Trofimovich bb14c16df6 Tried to improve code readability.
Now rule states and default state are added to DFA in separate
independent passes.

Removed 'bSaveOnHead' DFA property as it can be calculated right
before setting initial state action.
2015-06-08 14:41:55 +01:00
Ulya Trofimovich 3bd3146e13 Track backup states only if DFA has default state. 2015-06-08 11:27:14 +01:00
Ulya Trofimovich 0d2d663110 Reduced redundant variable.
Variables 'accept' and 'accfixup' were assigned both only once and
in the same place and used to do the same thing.
2015-06-07 13:59:48 +01:00
Ulya Trofimovich 3e01956eaf Fixed bug #60 "redundant use of YYMARKER".
Bug description: sometimes re2c would generate code that backups
current input position (e.g. 'YYMARKER = YYCURSOR'), but wouldn't
generate code that restores backuped position (e.g. 'YYCURSOR =
YYMARKER').

Analyses: DFA may have overlapping rules (e.g. "a" and "aaa").
In such cases, if the shorter rule matched, lexer must attempt to
match the longer one. If the longer rule also mathed, then lexer
prefers it to the shorter rule. If the longer rule didn't match,
lexer must backtrack input position to the point when the shorter
rule matched. In order to be able to backtrack, re2c must generate
backup code (e.g. 'YYMARKER = YYCURSOR') and restore code (e.g.
'YYCURSOR = YYMARKER').
In some rare cases DFA has overlapping rules, but if the shorter rule
matched, then the longer rule will always match (perhaps on an
arbitrary long input string), e.g.:
    /*!re2c
        [^]+ "a" { 1st }
        "b"      { 2nd }
    */
In this cases there's no need to generate backup code for 2nd rule:
lexer will either encounter final "a" and the 1st rule will match
or YYFILL will not return; anyway, restore code will never be run.
re2c used to output backup code but not restore code in such cases.
This is the bug: backup code is useless without restore code and
should be omitted.

In future re2c should warn about such cases (when the shorter of
two overlapping rules is shadowed by the longer one).

The fix: postpone insertion of save actions (those with backup code)
untill it is known if restore code will be generated.
I also removed obsolete global variable 'bUsedYYMarker', which was
always set to 'true' (it should be per-DFA, not per-block configuration
anyway).
2015-06-06 18:51:27 +01:00
Ulya Trofimovich ebadef2015 Fixed bug #59 "bogus 'yyaccept' in '-c' mode".
We have one 'yyaccept' initialization per re2c block. Each block
consists of one or more DFA (multiple DFA in '-c' mode in case of
multiple conditions). Each DFA may or may not use 'yyaccept'
(that is, save 'yyaccept' in some states and have a dispatch state
based on saved 'yyaccept' value).

Description of the bug: in '-c' mode, sometimes a DFA would have
states that save 'yyaccept', but no dispatch state that uses that
saved values. DFA didn't actually need 'yyaccept' (all the
assignments vanished if other conditions that need 'yyaccept' were
removed).

The essence of the bug: re2c decided whether to output 'yyaccept'
related stuff on a per-block basis: for multiple conditions in the
same block, the same decision was made (if any condition needed
'yyaccept', all of them would to output it).

The fix: 'yyaccept' initialization should be done on a per-block
basis, while assignments to 'yyaccept' should be done on a per-DFA
basis. Also, 'yyaccept' initialization must be delayed, while
assignments to 'yyaccept' must not.

Note: we may consider per-DFA 'yyaccept' initialization (have a
local 'yyaccept' variable per DFA). This wouldn't conflict with '-f'
switch (as it might seem) as long as we name all the variables
'yyaccept' and don't generate any 'yyaccept' initializations with '-f'.
2015-06-04 22:25:03 +01:00
Ulya Trofimovich c25bfa17f4 Use autoconf to locate bison. 2015-06-02 22:54:01 +01:00
Ulya Trofimovich 658b27b00a Respect user CXXFLAGS.
As automake manual (chapter 27.6 "Flag Variables Ordering") states,
CXXFLAGS is a user variable and should be left for users to override
C++ compiler flags. Thus we should leave CXXFLAGS as is and modify
AM_CXXFLAGS insted.
2015-06-02 22:29:19 +01:00
Ulya Trofimovich f59bcc5ab4 Added missing header (revealed by mingw build). 2015-06-02 17:16:27 +01:00
Ulya Trofimovich 4429526b43 Check CXXFLAGS in configure.
Instead of unconditionally setting CXXFLAGS in Makefile.am,
check the presence of a flag in configure.ac. If the flag is
present (that is, an attempt to compile an empty C++ program with
this flag is successful), then it is added to CXXFLAGS.

Now one can add *any* compiler flag in configure.ac without
worrying about portability.
2015-06-02 16:58:53 +01:00
Ulya Trofimovich b2bc24704e Support 'make distcheck'.
The only problem with 'make distcheck' was that we needed write
access to top source directory ('make' wanted to overwrite bootstrap
parser if it was built with bison and 'make check' wanted to create
temporary files in 'test/' directory).

This commit fixes it:
    - 'make' doesn't try to overwrite bootstrap if it is identical
      to the existing one (must always be true for 'make distcheck')
    - testing script makes a temporary directory and keeps all
      temporary files there. If some tests failed, temporary files
      for them are left and test sources and reference results are
      copied into temporary directory to make debug more convenient.

This commit makes use of 'make distcheck' in release script.
2015-06-02 13:19:50 +01:00
Ulya Trofimovich 9fcd864050 Fixed build system to support automake's 'subdir-objects' feature.
As I updated automake to version 1.15 it began to produce lots of
warnings about 'subdir-objects' not used when it should have been.
Turns out that 'subdir-objects' will be on by default in 2.0.

So I tried to turn on 'subdir-objects' and builds began to fail:
automake didn't expand '$(sourcedir)' and '$(builddir)' prefixes.
I erroneously prepended these prefixes in commit
38f526d044 "Updated build system.",
as commit message says:
...
    Makefile.am:
        - explicitly prefixed all file names with $(srcdir) or $(builddir)
...

But automake prepends these prefixes already where necessary, except
for custom rules with side effects: if a custom rule touches some
files that are not explicit targets or dependencies of this rule,
then automake won't find these files unless they are in build directory.
We have such side-effectful custom rules:
    - parser rule produces multiple files and touches bootstrap files
    - scanner rule touches bootstrap file
    - doc rules touch bootstrap files
Multiple files is a common problem of make. Bootstrap introduces
circular dependency, since bootstrap files need to be updated after
they've been used. So it's hard to get rid of side effects in these
rules.

This commit enabels 'subdir-objects' feature and removes all prefixes
in variables and adds them in side-effectful custom rules (for files
from source directory, not for files from build directory). It also
makes use of '$@' and '$<' special variables in custom rules (which
makes side effects more explicit).

Still I don't yet fully understand how automake uses things like
'$(sourcedir)' and '$(builddir)' and their relation with 'subdir-objects'
(it's probably related with non-recursive makefiles).
2015-06-02 12:34:09 +01:00
Ulya Trofimovich e5221e1259 Enable silent builds by default. 2015-06-01 22:59:08 +01:00
Ulya Trofimovich 7f326376eb Ignore one more autoconf-generated script. 2015-06-01 11:43:26 +01:00
Ulya Trofimovich 4a9f33ae99 Removed remnants of CVS ("# $Id$" in the beginning of some files) 2015-06-01 11:42:23 +01:00
Ulya Trofimovich 9153d0d80a Use autoreconf.
As stated by autoconf manual, autoreconf is more portable than
self-written scripts because aclocal may be removed in future.
2015-06-01 11:23:38 +01:00
Ulya Trofimovich a513afc31f Split header and appropriate source file into smaller parts. 2015-05-28 21:10:45 +01:00
Ulya Trofimovich 56c5aa3768 Moved another utility class to a separate file in 'src/util/'. 2015-05-28 18:40:41 +01:00
Ulya Trofimovich 27420c7a27 Moved utility class to a separate file in 'src/util/'. 2015-05-28 18:26:10 +01:00
Ulya Trofimovich bd68a29a15 Don't output newline instead if label in initial DFA state.
Rationale: the equivalence of initial label to
're2c::label_counter_t::FIRST' is NOT a proper criterion
and pretty-printing shouldn't rely on it. The real criterion
is something like "(first re2c block OR any use block in '-r'
mode) AND first condition in'-c' mode", but it's spurious and
introduces unnecessary complications.

Droping this newline allows us drop equivalence operator for
labels.

Used the following bash script to ensure that all the changes
in tests are caused by missing newline(s):

    #!/bin/bash

    for f2 in *.temp
    do
        f1=${f2%.temp}

        diff1=`diff $f1 $f2 | grep '^< ' | wc -l`
        diff1_line=`diff $f1 $f2 | grep '^< #line' | wc -l`
        diff1_newline=`diff $f1 $f2 | grep '^< $' | wc -l`
        diff2=`diff $f1 $f2 | grep '^> ' | wc -l`
        diff2_line=`diff $f1 $f2 | grep '^> #line' | wc -l`

        # missing: only newlines and line directives
        if [[ $diff1 -ne $((diff1_line + diff1_newline)) ]]
        then
            echo "FAIL1: $f1"
            exit 1
        fi

        # added: only line directives
        if [[ $diff2 -ne $diff2_line ]]
        then
            echo "FAIL2: $f1"
            exit 1
        fi

        # the number of missing line directives
        # equals to the number of added line directives
        if [[ $diff1_line -ne $diff2_line ]]
        then
            echo "FAIL4: $f1"
            exit 1
        fi
    done

    echo "OK"
2015-05-28 12:16:06 +01:00
Ulya Trofimovich a28f4b04f6 Introduced a distinct type for labels. 2015-05-28 11:45:11 +01:00
Ulya Trofimovich ff66ec1a8d Moved label assignment out of global scope to 're2c::OutputFile'.
Now label assignment is done with the help of a simple class
're2c::Label' that has very few operations.
2015-05-27 22:24:19 +01:00
Ulya Trofimovich 128611ad3e Some renaming and comment updating. 2015-05-27 17:26:22 +01:00
Ulya Trofimovich 17f3d99119 Added some more on 're2c:startlabel = <integer>;' configuration. 2015-05-27 16:48:32 +01:00
Ulya Trofimovich 71262eb9b6 Clarified which label is used.
Label of the first state must be used rather than some obscure label
relative to start label (which is itself quite obscure).
2015-05-27 16:33:22 +01:00
Ulya Trofimovich 0d19c57084 Isolated label counting. 2015-05-27 15:04:26 +01:00
Ulya Trofimovich eda463ec96 Separated code generation for DFA actions and DFA states.
Removes debugging utilities for DFA states (we should either add
debug builds explicitely or throw away temporary debug stuff).
2015-05-27 13:04:53 +01:00
Ulya Trofimovich 38d0a271db Gather all label counting in one place prior to code generation. 2015-05-27 12:52:02 +01:00
Ulya Trofimovich 7893fda164 Moved start label configuration out of global scope.
There are two configurations:
1. re2c:startlabel = <integer>;
2. re2c:startlabel = <string>;
The scope of these configurations is the scope of current re2c block.
2015-05-27 11:50:55 +01:00
Ulya Trofimovich 2ede5a7546 Output user-defines start label in the appropriate place.
Before this commit, given the following example:
    /*!re2c
            re2c:startlabel = "start";
            [^]* {}
    */
re2c would generate the following code:
    {
            YYCTYPE yych;
            goto yy0;
    yy1:
    start:
            ++YYCURSOR;
    yy0:
            if (YYLIMIT <= YYCURSOR) YYFILL(1);
            yych = *YYCURSOR;
            goto yy1;
            {}
    }
where "start:" falsely corresponds to "yy1:" rather to "yy0:".
(The important property of this example is that DFA has arrows
to initial state.) This commit fixes this behavior:
    {
            YYCTYPE yych;
    start:
            goto yy0;
    yy1:
            ++YYCURSOR;
    yy0:
            if (YYLIMIT <= YYCURSOR) YYFILL(1);
            yych = *YYCURSOR;
            goto yy1;
            {}
    }
2015-05-26 21:34:56 +01:00
Ulya Trofimovich e315bb4526 Don't hide the ugly fact that default state in '-f' mode is always state 0.
In '-f' mode, state dispatch generation can be triggered in two ways.
Both ways use 're2c::OutputFile::insert_state_goto', which generates
state dispatch only if it hasn't been already generated. The two ways
are:
1. Explicitly, using '/*!getstate:re2c*/'. In this case default state
   must be state 0 because it's hardcoded in the invocation of
   're2c::OutputFile::insert_state_goto' in 'src/parse/scanner_lex.re'.
2. Implicitly, in 're2c::DFA::emit'. In this case default state must
   be state 0 because if 'prolog_label' is not 0, it means that it's
   not the first time 're2c::DFA::emit' is called and state dispatch
   has already been generated.

This commit makes it explicit that re2c always uses state 0.

Note:
    Currently in '-f' mode re2c generates one global dispatch for
    the whole file (the enumeration of yyFillLabel's is also global).
    All re2c blocks share the same state dispatch, so in '-f' mode all
    re2c blocks must reside in the same function and must be parts of
    the same lexer (exception: in '-r' mode re2c generates one state
    dispatch per use block).

    This is clearly an ugly limitation: one is forced put disconnected
    lexers in different files in '-f' mode.

    Now re2c provides conditions as a way to express related blocks,
    so if users used multiple blocks only for unrelated lexers, we
    could safely limit the scope of state dispatch to a single block.
    But conditions can conflict with other re2c features, they are
    a bit broken and I'm pretty sure some users use multiple blocks
    (e.g. I used to do it).

    Thus we cannot just make '-f' generate state dispatch on per-block
    basis (there're some other obstacles: it's not quite clear which
    block '/*!getstate:re2c*/ directive is related to, etc.).

    I leave the situation 'as is' until better times (when lexer-
    parser loop is fixed and the whole code generation model is more
    robust).
2015-05-26 14:00:01 +01:00
Ulya Trofimovich c4a3724540 Clarify which label is relevant to initial state.
(see commit 4ab969deca)
2015-05-26 12:34:57 +01:00
Ulya Trofimovich 3a54bfaf54 Compare DFA states rather than labels.
(see commit 923f4c5559)
2015-05-26 12:24:48 +01:00
Ulya Trofimovich 4ab969deca Clarify which label is relevant to initial state.
Initial state is different from all other states in that should
not advance YYCURSOR when it's entered first time (when DFA is
entered). But it should advance YYCURSOR like any normal state if
it's entered from any other part of DFA (other DFA states may well
lead to the inital state, e.g. '[^]*')

That's why inital state is split into two parts, each marked by a
separate label: normal state label points to the code that advances
YYCURSOR, and special label points right after that code (skips it).

It happens so that normal state label is equal to special initial
label plus one, but we shouldn't rely on that.
2015-05-24 21:38:55 +01:00
Ulya Trofimovich 81c87ee88c Clarify that initial state stores 'start_label', not some random label. 2015-05-24 21:33:18 +01:00
Ulya Trofimovich 923f4c5559 Compare DFA states rather than labels.
This is first step to postpone labelling states until all the
code is actually generated (in the form of some structure in
memory) and it's time to pretty-print it to file.

Labels shouldn't be mixed up with states (in particular, they
shouldn't be used as a state identifier).
2015-05-21 14:38:13 +01:00
Ulya Trofimovich fd13406cb9 Updated version to 0.14.4.dev 2015-05-20 13:48:34 +01:00
Ulya Trofimovich 45c7f26041 Release 0.14.3. 2015-05-20 13:22:26 +01:00
Ulya Trofimovich 999be5b366 Added simple test for yacc-style brackets (see patch #27) 2015-05-20 13:17:12 +01:00
Ulya Trofimovich b068f3ad2e Fixed '#27 re2c crashes reading files containing %{ %}' (patch by Rui) 2015-05-20 13:08:12 +01:00
Ulya Trofimovich 17bfdc6dd9 Regenerated documentation (changed by previous commit). 2015-05-20 10:45:31 +01:00
Ulya Trofimovich d607832645 Finally removed auxiliary code generation pass to 'null device'.
This pass was used to gather statistics:
    - which labels are used (to avoid 'unused label' warnings from
      C/C++ compiler)
    - in '-f' mode, how many times YYFILL is called (to generate
      dispatch to the arrpopriate YYFILL call and resume lexing from
      there)

This commit deals with second case: it makes counting YYFILL calls
independent of auxiliary pass. Counting relies on variable
're2c::last_fill_index', which is updated in 're2c::need' function
(note that it is crucial that 're2c::need' is always called prior
to generation of state dispatch).

Also fixed documentation for '-f'.
2015-05-20 09:34:26 +01:00
Ulya Trofimovich 77ed90ca54 Pass only that part of output needed by 're2c::State::emit'. 2015-05-19 18:53:35 +01:00
Ulya Trofimovich d41cef7546 Fixed clang's "warning: declaration shadows a local variable [-Wshadow]" 2015-05-19 18:45:55 +01:00
Ulya Trofimovich ef2b9a144c 're2c::emit_init' doesn't generate anything useful in .dot mode. 2015-05-19 18:39:04 +01:00
Ulya Trofimovich 350d5bf3b0 Another part of tracking label usage moved out from codegen.
This is part of effort to reduce code generation to 'null device'
(the same code is generated twice only to gather statistics on
label usage). In order to reduce this evil pass, we should be able
to track label usage before code generation.
2015-05-19 18:19:24 +01:00
Ulya Trofimovich a1638639d7 Simplified 're2c::Action' class and its usage.
Replaced inheritance hierarchy with tagged union.
2015-05-19 12:53:24 +01:00
Ulya Trofimovich f61fe9d61a Fixed clang's "warning: declaration shadows a local variable [-Wshadow]" 2015-05-18 12:58:04 +01:00
Ulya Trofimovich d1ebc44352 Don't copy <*> regexps for each condition.
There're two major things to care about in this situation:
1. <*> rules must have the lowest priority: in order to guarantee
   it, we re-iterate <*> regexps after all other rules have been
   parsed and fix <*> regexps priority.
2. <*> regexps must be compiled to instrictions separately for each
   condition: this is guaranteed by assigning them
   're2c::RegExp::PRIVATE' attribute.

Note that 're2c::RuleOp::accept' member stores rule priority.
These priorities don't have to be consecutive, only the right order
must be maintained. Later on in 're2c::DFA::prepare' they result in
consecutive 'yyaccept' values.
2015-05-16 12:01:58 +01:00
Ulya Trofimovich ebea1d58ff Forbid copying of 're2c::Substr'.
Removed useless methods (most of them became useless after
're2c::Str' removal) and obsolete autoconf check for 'strndup'.

Removed 'Scanner::token' methods. They used
'Scanner::check_token_length', which was pretty useless:
1. checking for the lower should have always succeed, because
   'Scanner::tok' is always set to buffer start in 'Scanner::fill'
   and if the token was too long, it's start will be lost anyway.
2. checking for the upper bound could fail if re2c dev passed some
   trash into it, but any normal function would do so and this is
   no particular reason to have special runtime checks here.
Now substrings are constructed in lexer, where all the lengths
and bounds are easier to verify from lexing context (for re2c dev).
2015-05-14 18:20:13 +01:00
Ulya Trofimovich 00b14f309b Removed obsolete 're2c::Str' stuff. 2015-05-14 16:37:54 +01:00
Ulya Trofimovich 957681c736 Pass unquoted strings to parsing functions.
In most cases re2c accepts single-quoted or double-quoted strings
in regexp specifications, but if flex-like syntax if enabled, then
re2c accepts unquoted strings.

Before this commit, functions that parse strings into regexps
expected quoted strings, and we had to add quotes in case of
flex-like syntax. That was very inconvenient and in fact
unnecessary, since the first thing parsing functions do is get rid
of quotes.
2015-05-14 13:58:29 +01:00
Ulya Trofimovich c66bbe0cee Now 're2c::Token' uses 'std::string' instead of 're2c::Str'. 2015-05-14 13:16:24 +01:00
Ulya Trofimovich 23d0e46782 Simplified handling of named definitions in parser.
Don't bother with named definitions in lexer, just pass them as
strings to parser. Parser will recognize named definitions, insert
them into symbol table and handle conflicts.

Use simple 'std::map' instead 're2c::Symbol' class (that hides
symbol table in class static member).

Use 'std::string' instead of 're2c::Str'. Due to bison limitations
we have to pass pointers to strings allocated on the heap and
carefully destroy them. The whole thing is quite error prone, so
maybe I'll make a small slab allocator for parser later on.
2015-05-14 12:25:24 +01:00
Ulya Trofimovich 8322a21500 Fixed mismatched new/delelte (found by valgrind).
What is allocated with 're2c::allocate<T>' (operator new), should
be freed with 'operator delete', not with 'delete' or 'delete []'.
2015-05-14 12:21:26 +01:00
Ulya Trofimovich df0a77409b Moved 're2c::Symbol' class to a separate header and source file. 2015-05-13 17:34:48 +01:00
Ulya Trofimovich 435ee69a8e Replaced 're2c::Str' with 'std::string'.
There's no point in using self-invented strings if one always
converts them to 'std::string' before actually using them.
2015-05-13 15:24:35 +01:00
Ulya Trofimovich bb25bad874 CXXFLAGS: removed -DPEDANTIC, added -Weffc++. Fixed warnings. 2015-05-13 15:07:01 +01:00
Ulya Trofimovich bfcac89577 Split 'src/dfa/dfa.h' into parts: DFA states, DFA actions, DFA. 2015-05-13 11:13:09 +01:00
Ulya Trofimovich 5731ba97f9 Moved functions declarations and typedefs to a proper place. 2015-05-12 17:00:09 +01:00
Ulya Trofimovich 7a2558c1fa Merged 'src/codegen/translate.cc' into 'src/codegen/print.cc'. 2015-05-12 12:51:30 +01:00
Ulya Trofimovich 14bf192969 Split 'src/codegen/code.cc' into parts.
First, DFA is built ('re2c::DFA::DFA'), then it must be prepared
for code generation: some states must be split, backtracking points
must be marked, etc. ('re2c::DFA::prepare'), then finally code
can be generated ('re2c::DFA::genCode').

I haven't yet fully decided whether second stage (preparing) is
closer to DFA construction in general (and thus should be moved to
'src/dfa') or to code generation (and should be moved to 'src/codegen').
Since it deals a lot with bitmaps, second variant will suffice for
now. Perhaps later on I'll split preparation into general and
codegen-related parts.
2015-05-12 12:26:07 +01:00
Ulya Trofimovich b9e788aa5d Renamed struct to avoid confusion.
're2c::BitMap' represents actual bitmaps used for code generation,
while 're2c::GoBitmap' (former 're2c::Bitmap') is a node type in
graph representation of the program right before code generation.

Names used in 're2c::Go' subsystem are really ugly and will be
renamed to something more sensible later on.
2015-05-12 11:32:11 +01:00
Ulya Trofimovich 5a794d5bc3 Moved 're2c::BitMap' methods to a separate source file. 2015-05-12 11:26:04 +01:00
Ulya Trofimovich 123d114a68 Removed some useless includes from 'src/codegen/code.cc'. 2015-05-12 11:05:08 +01:00
Ulya Trofimovich e14a275c39 Moved lexing functions to proper file.
For some reason 're2c::Scanner' methods were defined in file
'src/codegen/code.cc'. Mpved them to 'src/parser/scanner.cc'
and renamed 'src/parser/scanner.re' to 'src/parser/scanner_lex.re'.
2015-05-12 10:57:27 +01:00
Ulya Trofimovich bc2681f744 Removed useless include. 2015-05-11 21:04:34 +01:00
Ulya Trofimovich abc40ff29c Reduced "src/codegen/print.h" dependency for some unrelated files.
This is the first part of effort to reduce the total number of
interdependencies between different files.

"src/codegen/print.h" contains some pretty-printing functions
mostly used for code generation. There two other cases where.
these functions can also be useful:
    1. debug: it's not yet well developed, just some messy chunks
       of code that are commented out
    2. error messages: character pretty-printing is not actually
       very useful, since error messages mostly contain printable
       characters (pieces of user-supplied input)
From the above I conclude that non-codegen files don't really need
"src/codegen/print.h". If this will change, I'll consider moving
this functions to src/util.
2015-05-11 17:46:26 +01:00
Ulya Trofimovich 64db3825e7 Improved source files layout.
Created a directory tree to group logically related source files
and clean up top source directory.
2015-05-11 13:46:26 +01:00
Ulya Trofimovich 4d32cf1eb7 Added mingw builds for windows.
To enable mingw build, confugure with "--host i686-w64-mingw32".
Simple 'make' will then build re2c.exe executable for windows.
Note that 'make bootstrap' will not work: it will try to run
re2c.exe in order to recompile scanner and this will surely fail.

Testing with wine can be done using 'make wtests'.
2015-05-11 11:13:34 +01:00
Ulya Trofimovich 56b7fe2428 Don't recompile scanner by default.
Since it will cause insignifacant changes in bootstrap files
which we'll have to commit every time.
2015-05-11 10:54:26 +01:00
Ulya Trofimovich d76b7a9135 Don't rebuild docs by default.
If we configure with "--enable-docs", then docs get rebuild every
time make is executed, and we'll have to commit these insignificant
changes every time, which is bad.
2015-05-11 10:41:01 +01:00
Ulya Trofimovich 38f526d044 Updated build system.
Major changes:
- Moved all re2c source files to a separate directory. Top source
  directory should only contain autotools source files and a few other
  files like README.

- Enabled out-of-source builds (and wrote a simple script build.sh
  that makes out-of-source build).

- Improved portable variant of <stdint.h> header (src/c99_stdint.h):
  now it relies only on some few defines in configure-generated
  src/config.h (instead of checking for MSVC version and relying
  on MSVC-defined stuff). Implementation follows C99 standard closely.

- Removed all windows-related build stuff. It was no use keeping it:
  it's been broken for a long time and I can't maintain it.

- Removed all RPM stuff: distro-maintainers use their own hacks anyway.
  Makefile.am is definetely the wrong place to keep such things.
  A separete script and .spec file is a better idea, but again, nobody
  uses it.

- added make target 'bootstrap' to make mainteiners' job easier.

- Merged lessons and examples into one.

- Updated README and doc/index.html.

- Run tests in parallel by default.

Changes concerning particular files:
- configure.ac:
    - removed autoconf version check: developers will need the right
      version anyway (otherwize autoconf will reject to work);
      users should use configure script provided by package
      distribution

    - removed GCC version (3 or above) check: it's pretty ancient
      and I don't know which features are missing anyway

    - removed some useless checks (which resulted in defines in
      src/config,h used by no one)

    - introduced some new checks (used by src/c99_stdint.h)

    - followed the advices of autoupdate

Makefile.am:
    - explicitly prefixed all file names with $(srcdir) or $(builddir)

    - removed windows and RPM related rules and targets

    - added target 'bootstrap'

    - sorted out automake variables
2015-05-08 23:09:00 +01:00
Ulya Trofimovich 090dd07600 Continued adding "--skeleton" switch.
Some renaming and cleanup.
2015-04-23 15:26:56 +01:00
Ulya Trofimovich e56d15a468 Continued adding "--skeleton" switch.
Simplified 'generate_paths_cover' a bit: NULL-state case is not
really needed, it's artificial and should be embedded into the
only case that needs it.
2015-04-22 23:24:43 +01:00
Ulya Trofimovich f5346a1608 Continued adding "--skeleton" switch.
Check possible overflow immediately.
2015-04-22 17:54:48 +01:00
Ulya Trofimovich 5bb44e7f4a Continued adding "--skeleton" switch.
Estimate the size of data to be generated rather than the number
of paths in DFA. Returns precise size or 'Skeleton::MAX_PATHS',
whatever is less. Estimate data size in both cases for all paths
or path cover.
2015-04-22 17:45:24 +01:00
Ulya Trofimovich 014b82d19f Continued adding "--skeleton" switch.
Use RAII-style object to auto-decrement visit counter when
leaving local scope.
2015-04-21 15:49:15 +01:00
Ulya Trofimovich b30b1818c5 Continued adding "--skeleton" switch.
Improved readability of overflow checks when counting the number
of paths.
2015-04-20 23:46:29 +01:00
Ulya Trofimovich f704960bcc Added portable version of <stdint.h>, converted the whole project. 2015-04-20 23:38:32 +01:00
Ulya Trofimovich eacd3d525c Continued adding "--skeleton" switch.
Generate all possible paths (with respect to range lower/upper
bounds) in case their total amount is less than
'Skeleton::PATHS_OVERFLOW'.
2015-04-20 17:21:48 +01:00
Ulya Trofimovich 29e99fe720 Continued adding "--skeleton" switch.
Be even more careful not to overflow path counter, check possible
multiplication overflow.
2015-04-20 15:03:57 +01:00
Ulya Trofimovich f1170e99ef Continued adding "--skeleton" switch.
Fixed backtracking error introduced by previous commit: shouldn't
return prematurely, need to unmark state as visited first.

Some renaming.
2015-04-20 13:43:31 +01:00
Ulya Trofimovich a74b6d4a8e Continued adding "--skeleton" switch.
Give up counting data when reached certain limit
('Skeleton::MAX_PATHS').
2015-04-20 13:26:25 +01:00
Ulya Trofimovich c8b5ac322f Continued adding "--skeleton" switch.
Code cleanup.
2015-04-19 23:11:32 +01:00
Ulya Trofimovich 86e29ab552 Continued adding "--skeleton" switch.
Keep all generated paths in memory (we are careful not to generate
too much of them, and we keep second part of data (positions) in
memory anyway).
2015-04-19 22:38:50 +01:00
Ulya Trofimovich d9f081e312 Continued adding "--skeleton" switch.
Simplified traversal of outgoing arrows when extending prefixes.
Instead of adding outgoing arrow sets (which was erroneous anyway:
they should remain unmodified for another recursion entry), simply
wrap iterator and keep iterating until both ingoing and outgoing
arrows are counted.
2015-04-19 22:05:46 +01:00
Ulya Trofimovich e03a3c9d22 Continued adding "--skeleton" switch.
Simplified construction of prefixes.
2015-04-17 18:51:29 +01:00
Ulya Trofimovich 92e33e31bb Continued adding "--skeleton" switch.
Renamed: 'Prefix' -> 'Path'.
2015-04-17 17:15:31 +01:00
Ulya Trofimovich 93c51642e8 Continued adding "--skeleton" switch.
More code cleanup: pre-initialize paths for final states and
default state, so that NULL can be used as a terminating condition
for path-generating function. Fixed memleaks.
2015-04-17 17:00:23 +01:00
Ulya Trofimovich 4e3dcd335f Continued adding "--skeleton" switch.
Code cleanup.
2015-04-16 16:38:46 +01:00
Ulya Trofimovich 1f620a12e9 Continued adding "--skeleton" switch.
Tried to simplify data generation a bit: construct skeleton states
so that there's no links to NULL state. Default state is
represented with a state that has no rule and zero outgoing
arrows. Final states are represented with a state that has a rule,
but zero outgoing labels.
2015-04-16 14:46:03 +01:00
Ulya Trofimovich 978e38e154 Continued adding "--skeleton" switch.
Code cleanup.
2015-04-15 15:09:45 +01:00
Ulya Trofimovich ba42821176 Continued adding "--skeleton" switch.
Code cleanup.
2015-04-15 15:02:23 +01:00
Ulya Trofimovich dfcdfd8b77 Continued adding "--skeleton" switch.
Reduced the amount of generated data (no exponential growth now).
Generate enough paths to cover all DFA transition (well, not
exactly all: only upper and lower bounds of a range). Respect
cycles (loop once).
2015-04-15 13:40:19 +01:00
Ulya Trofimovich b35d196d7d Makefile.am: dropped distfiles for MSVC (they are broken anyway) 2015-04-13 10:23:57 +01:00
Ulya Trofimovich fec9902629 Code cleanup. 2015-04-08 16:43:16 +01:00
Ulya Trofimovich af34861d0a Continued adding "--skeleton" switch.
Use a separate DFA-like structure for DFA skeleton. This allows
to optimize skeleton states for fast traversal (group transitions
by destination state) and avoid messing with the original DFA.

Added 'count' method to estimate the the amount of data that will
be generated (it worked too slow for the origianl DFA with
ungrouped transitions).
2015-04-08 12:58:59 +01:00
Ulya Trofimovich dddf15692a Continued adding "--skeleton" switch.
Output input data to a separate file (otherwize we'll have to
keep all generated data in memory, cause output has a complex
structure and cannot be written to file until it's fully
generated)

This reduces memory usage significantly (so that there remain no
memory consumption problems with "--skeleton" switch). However
on some files re2c generated too much data, e.g. case-insensitive
strings:

/*!re2c
	'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' {}
*/

Exponential growth is a bad thing; must deal with it somehow.
Time grows exponentially as well, of course.
2015-04-07 17:01:46 +01:00
Ulya Trofimovich 0834dff1bb Continued adding "--skeleton" switch.
Check for rule match in final states.
2015-04-06 22:11:05 +01:00
Ulya Trofimovich ab2f22ebf8 Continued adding "--skeleton" switch.
Generate check for input position in final states: first check
that input position equals to the expected one; second advance
input position to the beginning of next DFA path (this may be
necessary when the generated lexer rollbacks: it should resume
with a new DFA path rather than some default characters remaining
after rollback).
2015-04-06 20:40:43 +01:00
Ulya Trofimovich a273fab32e Continued adding "--skeleton" switch.
Fixed range lower bound tracking when generating input strings
from DFA.
2015-04-06 20:15:29 +01:00
Ulya Trofimovich 261353ba77 Continued adding "--skeleton" switch.
When generating DFA paths respect range lower bound as well as
upper bound.
2015-04-06 19:08:02 +01:00
Ulya Trofimovich c6178c064d Continued adding "--skeleton" switch.
Output generated strings directly to file instead of storing them
in memory.
2015-04-06 18:44:59 +01:00
Ulya Trofimovich ea088ac388 Continued adding "--skeleton" switch.
Track exact number of characters to be consumed on each input
string. Note that it's not equal to string length, since many
strings end up with characters from default transitions: on such
strings lexer must rollback to the latest backtracking point (that
is, the latest accepting state).
2015-04-06 16:41:49 +01:00
Ulya Trofimovich 36abdd25de Continued adding "--skeleton" switch.
Moved input-string-generation-from-DFA algorithm earlier, to the
point when DFA is barely constructed and contains only 'Match'
states and starting state (no saving, accepting or split states).
This simplifies string generation: if destination state is NULL,
it is either next to final state (if all spans lead to it), or
default state (if some spans lead to other states).
2015-04-06 05:11:56 +01:00
Ulya Trofimovich 30806635b5 Removed useless type of DFA state.
'Enter' was encapsulated by 'Initial' and never used on its own.
2015-04-05 15:39:29 +01:00
Ulya Trofimovich 337e8a20ab Continued adding "--skeleton" switch.
Fixed backtracking in deriving-input-data-from-DFA algorithm.
2015-04-05 12:43:11 +01:00
Ulya Trofimovich 9841a4c0de Determine action type in a simpler way. 2015-04-03 22:40:44 +01:00
Ulya Trofimovich 86d9f2f08c Continued adding "--skeleton" switch.
Tried to sort out various DFA states and how they influence code
generation. Added explicit type field to all actions.
2015-04-03 22:30:13 +01:00
Ulya Trofimovich d33f245778 Removed useless NULL check (all NULL destination states handled in DFA::prepare). 2015-04-03 22:23:36 +01:00
Ulya Trofimovich 5818aee2c9 Continued adding "--skeleton" switch.
A naive attempt to generate input strings from DFA. The problem is,
if the number of spans equals 1, it's hard to determine whether
it's some kind of a 'transit' state or a normal state with just one
span. All states have spans, but do they use them? The situation is
further complicated with 'readCh' which makes it hard to trace how
actions influence input operations.
2015-04-02 15:31:14 +01:00
Ulya Trofimovich 6b18c88354 Omit useless check for NULL: default transitions are handled in DFA::prepare 2015-04-02 15:07:26 +01:00
Ulya Trofimovich e19efe8bf0 Some output should be generated with "--skeleton", but not with "-D" 2015-04-02 15:04:45 +01:00
Ulya Trofimovich a7b8ae7f27 Makefile.am: added "-O2" to CXXFLAGS 2015-04-02 15:03:40 +01:00
Ulya Trofimovich 89978d1ca5 Prettified debug output. 2015-04-02 15:02:33 +01:00
Ulya Trofimovich 13d32d15d4 Continued adding "--skeleton" switch.
Generate prolog and epilog in the form of a for-loop. The body
of the loop is the hard-coded DFA. The code in DFA final states
is substituted with "continue" statements.
2015-03-30 14:41:29 +01:00
Ulya Trofimovich a3e4bc9d52 Started adding "--skeleton" switch. 2015-03-27 21:35:49 +00:00
Ulya Trofimovich 03208a8de3 Testing script: trap SIGINT in child threads.
Now 'Ctrl+C' is handled as in single-threaded script: all threads
stop working.
2015-03-27 14:55:11 +00:00
Ulya Trofimovich f2565c463e A little code cleanup. 2015-03-26 16:45:57 +00:00
Ulya Trofimovich 6a5cc88e4b Don't output YYCTXMARKER stuff in .dot mode.
Added test that revealed error.
2015-03-26 16:42:58 +00:00
Ulya Trofimovich 22e77a4a47 Run tests in parallel with "-j<threads>" option. 2015-03-26 16:37:25 +00:00
Ulya Trofimovich b58da35fa1 Comment 2015-03-26 16:31:20 +00:00
Ulya Trofimovich 89ea6cd112 Added text file 'sf-cheatsheet' to make some notes about sourceforge administration. 2015-03-26 16:27:21 +00:00
Ulya Trofimovich 84c1f71db0 Removed unused funtion. 2015-03-26 16:26:51 +00:00
Ulya Trofimovich 764efed942 Added full another test for bug #57. 2015-03-26 12:00:58 +00:00
Ulya Trofimovich 9fba8277ca Updated version to 0.14.3.dev 2015-03-25 21:34:42 +00:00
Ulya Trofimovich 5b10c5efb0 Release 0.14.2. 2015-03-25 21:21:03 +00:00
Ulya Trofimovich 1a97c678d5 Fixed bug #57: Wrong result only if another rule is present
When making regexp alternative, only 'RegExp::PRIVATE' attribute
should be propagated. Propagating 'RegExp::SHARED' attribute is
a mistake, as can be observed from the following example:

    name = "smth1";
    "smth2" | name | "smth3" { ... }
    name                     { ... }

Here, 'name' must have 'RegExp::PRIVATE' attribute, but it gets
broken after alternation. See #bug57 or test 'bug57.re' for full
working example.
2015-03-25 16:25:10 +00:00
Ulya Trofimovich 8034cccb74 Make 'Go' hierarchy independent of relabelling.
This allows to move 'Go' initialization loop to 'DFA::prepare'
and thus avoid ugly check if it is already initialized (it can
happen in '-r' mode when the same DFA is used multiple times).
Now that we store 'State *' pointers instead of labels in
'CpgotoTable', relabelling won't affect the generated code.
2015-03-18 15:01:41 +00:00
Ulya Trofimovich ea2b84586d - Track used labels in a separate traversal of 'Go' graph
(first part of effort to reduce codegen to null device)
- Properly destruct 'Go' graph (46 test failing with '--valgrind'
  because of early exiting on errors)
2015-03-18 14:35:19 +00:00
Ulya Trofimovich 44c6aeefea Abstracted common used constant in a class variable. 2015-03-18 11:08:44 +00:00
Ulya Trofimovich 79d56ad711 Separated 'Go' stuff: construction and output. 2015-03-18 10:55:43 +00:00
Ulya Trofimovich f8e1f458f8 Reduced redundant parameter. 2015-03-17 16:24:46 +00:00
Ulya Trofimovich fa88d997f2 Split control flow codegen in two phases:
- First, re2c builds a complex structure where it stores
  all control flow codegen decisions: nested ifs or switches,
  bitmaps or computed gotos, etc.
- Second, this structure is traversed and code is generated.

This differentiation is necessary to compute some statistics
(e.g. used labels) in advance, before code generation.
2015-03-17 16:00:52 +00:00
Ulya Trofimovich 5c7d6b06f4 Extracted duplicated code to a function. 2015-03-15 15:09:46 +00:00
Ulya Trofimovich 165b10500d Updated test results (changed due to the previous commit). 2015-03-15 14:56:57 +00:00
Ulya Trofimovich 51c9809275 Removed YYDEBUG call before switch.
We don't call YYDEBUG in analogous situation (when if/else is used
insted of switch), and it seems redundant anyway.
2015-03-15 14:43:45 +00:00
Ulya Trofimovich cb1e87f221 Don't segfault if span has zero length. 2015-03-13 18:34:14 +00:00
Ulya Trofimovich 813167be67 Simplified codegen decision between switches/ifs.
All tests pass.
The previous condition made more sense: it was clear that the
author intended to consider some frequent corner cases.
But the condition was very tangled and yet too heuristic,
so I substituted it with a meaningless, but simple one.
I'm planning to simplify it even more later on.
2015-03-12 21:49:55 +00:00
Ulya Trofimovich 881da4c3c2 Removed unreachable condition. 2015-03-11 16:42:08 +00:00
Ulya Trofimovich 800e9d80a3 Number of high (wide) spans not necessarily depends on code unit size. 2015-03-11 16:32:56 +00:00
Ulya Trofimovich 56f1e9974b Moved bitmap statistics counting inside of 'Go' class. 2015-03-11 15:46:52 +00:00
Ulya Trofimovich 1597947cea Moved bitmap statistics to 'Go' class. 2015-03-11 15:02:19 +00:00
Ulya Trofimovich fe478fb3a0 Moved methods out of class. 2015-03-11 14:45:12 +00:00
Ulya Trofimovich e7b58cbfa3 Reduced useless wrappers. 2015-03-11 12:52:32 +00:00
Ulya Trofimovich e42003d805 Pass limited span instead of checking range all the time. 2015-03-11 12:46:58 +00:00
Ulya Trofimovich 22bd4fbc93 Simplify handling of high/low spans.
Spans are already ordered, so to get high (wide) spans,
all we need is to find first span with upper bound >0x100
and point at it.
2015-03-11 10:52:05 +00:00
Ulya Trofimovich f4b35b97a5 Moved wide span barrier to 0x100 rather than 0xFF.
0x100 corresponds to condition 'encoding.szCodeUnit () <= 1',
cause field 'ub' in 'Span' means upper bound of char interval.
2015-03-10 21:53:11 +00:00
Ulya Trofimovich 9329ee4546 Removed useless statistics counter.
Verified with 'assert (dSpans >= lTargets);'
2015-03-10 21:33:13 +00:00
Ulya Trofimovich dd94f58d2e Reclaced class member with a local variable. 2015-03-10 18:53:31 +00:00
Ulya Trofimovich 2bbc0c704e Replaced class member with a local variable. 2015-03-10 18:47:31 +00:00
Ulya Trofimovich caed1cf71d Eliminated redundant variable. 2015-03-10 18:41:50 +00:00
Ulya Trofimovich ab5cdde889 Removed unused variable. 2015-03-10 17:07:10 +00:00
Ulya Trofimovich cc9435cf74 Removed dead code. 2015-03-10 16:01:15 +00:00
Ulya Trofimovich 35ec584b39 Extracted common functionality in codegen -g and -b flags. 2015-03-10 15:58:29 +00:00
Ulya Trofimovich b67be80d35 Removed obsolete condition (makes no sense in single-pass mode). 2015-03-07 20:54:08 +00:00
Ulya Trofimovich 8a017c71bb Simplified .dot codegen:
- draw a single arrow for all transitions between two given states
- label all arrows with corresponding character ranges in square
  brackests (no "default" label, single characters also appear in
  square brackets)
- .dot output became much smaller, thus pictures are drawn faster
  and generally look better: e.g. it takes ~10x less time to draw
  PHP lexer and the resulting graph is shaped better.
2015-03-07 20:00:06 +00:00
Ulya Trofimovich 841c06300b Simplified switch generetion in codegen. 2015-03-05 16:47:25 +00:00
Ulya Trofimovich d9a7de6b90 Continued separating .dot case from other cases in codegen. 2015-03-04 17:26:40 +00:00
Ulya Trofimovich 9b3f3fc491 Continued separating .dot case from other cases in codegen. 2015-03-04 17:23:28 +00:00
Ulya Trofimovich b75521a8c0 Continued separating .dot case from other cases in codegen. Added test. 2015-03-04 17:15:38 +00:00
Ulya Trofimovich a54722bd46 Continued separating .dot case from other cases in codegen. 2015-03-04 15:43:43 +00:00
Ulya Trofimovich 580f86bf11 Continued separating .dot case from other cases in codegen. 2015-03-04 15:41:10 +00:00
Ulya Trofimovich 2f82ce51d4 Started to separate .dot case from other cases in codegen. 2015-03-04 15:16:34 +00:00
Ulya Trofimovich d36af2c84f Removed dead code.
Used 'if (next) assert(next->label == from->label + 1);'
to ensure that code is really dead (and 'next' is always
the next state to 'from').
2015-03-04 13:12:19 +00:00
Ulya Trofimovich d5f999b792 Hided 'OutputFile' structure. 2015-03-02 13:54:11 +00:00
Ulya Trofimovich f7af77b370 Code cleanup in input/output:
- Use 'open' function instead of checking return status
  (one may forget to check return status, but if one forgets to
  open file, the error will be obvious)
- Introduced separate file type for header.
  Header is much simpler than output, it doesn't need delayed
  code fragments and can be generated in destructor.
2015-03-02 12:41:53 +00:00
Ulya Trofimovich 44cf3edcfa Updated version to 0.14.2.dev 2015-02-28 00:04:20 +00:00
Ulya Trofimovich b8e08c19d1 Release 0.14.1. 2015-02-27 23:52:00 +00:00
Mike Gilbert 23c26a75a1 Pad version with '0' instead of nulls
This produces a more usable output for scripts.
2015-02-27 23:42:59 +00:00
Ulya Trofimovich 2011ff7306 Finally get rid of 'file_info' and 'stream_lc.h' 2015-02-27 23:42:01 +00:00
Ulya Trofimovich 0e2ce85feb Reduce 'file_info' usage (in order to get rid of 'stream_lc.h'). 2015-02-26 13:23:02 +00:00
Ulya Trofimovich 283bfdb95e 'token.h' no longer depends on 'file_info'.
Part of campaign to remove 'stream_lc.h'.
2015-02-26 12:37:07 +00:00
Ulya Trofimovich 44dd876e6b Now input stream is simple 'FILE *'.
This is first part of campaign to remove 'stream_lc.h'.
2015-02-26 12:32:55 +00:00
Ulya Trofimovich 9eca3fed2e Dead code elimination. 2015-02-26 11:41:15 +00:00
Ulya Trofimovich e7a3c0ba3b Removed unused enum members.
I was unsure if delayed generation was also needed for genCondGoto
and genCondTable; so I kept those enum members as a reminder. Now
I know that all conditions are known by the moment re2c block is
parsed and code generation starts.
2015-02-26 10:48:41 +00:00
Ulya Trofimovich 21688c8923 Moved operator definition to where it belongs. 2015-02-26 10:36:16 +00:00
Ulya Trofimovich 57c14cfbe9 One pass.
Second pass was used because some information (which influences
early parts of the generated code, e.g enum with condition names
or YYMAXFILL definition) becomes available only at the end of first
pass.

I isolate all (I hope so) these things and generate stubs for them,
which are filled later. I restructured output as follows: the whole
output consists of source and header, each of them is a list of
blocks (corresponding to re2c blocks in source file), each block
is a list of code fragments (which can be either regular strings
with code or stubs that will be filled later).
2015-02-25 23:13:55 +00:00
Ulya Trofimovich 13cc72c88b Updated version to 0.14.1.dev 2015-02-23 18:51:38 +00:00
Ulya Trofimovich c701e89868 Release 0.14. 2015-02-23 17:28:35 +00:00
Ulya Trofimovich b9cca15829 Makefile.am: added bootstrap/re2c.1 to dist files. 2015-02-23 17:25:26 +00:00
Ulya Trofimovich 3bb5ebb75c Makefile.am: copy re2c.1 to bootstrap files 2015-02-23 17:23:58 +00:00
Ulya Trofimovich 0ba4ae9078 Makefile.am: added forgotten header. 2015-02-23 17:18:02 +00:00
Ulya Trofimovich 875957f2fb Makefile.am: removed obsolete MSVC files and added forgotten header. 2015-02-23 17:15:40 +00:00
Ulya Trofimovich cdd257bf78 Updated CHANGELOG and index.html 2015-02-23 17:09:20 +00:00
Ulya Trofimovich c008c9d432 Updated docs. 2015-02-23 17:00:45 +00:00
Ulya Trofimovich 2ec314648d Added tests from PHP repository: https://github.com/php/php-src
Test results are almost identical to re2c-0.13.6
(there're some few changes, I believe they are due to
commit 255262b029 and
completely harmless).
2015-02-23 13:30:42 +00:00
Ulya Trofimovich be31c94141 Renamed YYEOI -> YYLESSTHAN 2015-02-23 12:04:38 +00:00
Ulya Trofimovich 2e6c7b8aa9 Revert "Renamed re2c primitives:"
This reverts commit 7f816a85b0.
2015-02-23 11:50:30 +00:00
Ulya Trofimovich 7f816a85b0 Renamed re2c primitives:
YYPEEK       ---> RE2C_PEEK
    YYSKIP       ---> RE2C_SKIP
    YYBACKUP     ---> RE2C_BACKUP
    YYBACKUPCTX  ---> RE2C_BACKUP_CTX
    YYRESTORE    ---> RE2C_RESTORE
    YYRESTORECTX ---> RE2C_RESTORE_CTX
    YYEOI        ---> RE2C_LESS_THAN

Updated tests and examples accordingly.

Renamed functions:

    expr_eoi        ---> expr_less_than
    expr_eoi_one    ---> expr_less_than_one
    stmt_backupctx  ---> stmt_backup_ctx
    stmt_restorectx ---> stmt_restore_ctx
2015-02-09 17:26:36 +00:00
Ulya Trofimovich 394d03aaf4 Fixed changelog formatting on re2c.org. 2015-01-18 20:27:58 +00:00
Ulya Trofimovich f968d82d75 Added some examples of "--input custom" usage.
Had to modify .gitignore to unmask README in subfolders.
2015-01-18 15:56:06 +00:00
Ulya Trofimovich ccbbcaafd9 Replaced "YYHAS (n)" with "YYEOI (n)".
The actual meaning of this primitive is to check if
there's not enough characters left in the input stream,
e.g. "(YYLIMIT - YYCURSOR) < n" or whatever else.
2015-01-18 14:12:16 +00:00
Ulya Trofimovich 46b9058de0 Added tests for "--input custom".
This implied modifying runtests.sh, as it couldn't handle
test names of the form "basename.--long-switch.re":
it inserted '-' in front of all switches.
2015-01-18 13:47:51 +00:00
Ulya Trofimovich 5771b8cf13 Removed "--input istream".
It's impossible to correctly implement this switch in general,
since not all istreams support seek (simplest counterexample:
std::cin).

Even for simple istreams like std::istringstream, proper
error handling requires adding something like "YYERROR ()".
2015-01-18 13:43:08 +00:00
Ulya Trofimovich 63b6d381ae A little cleanup of new input API:
- moved enum and pretty-printing functions to a class
- renamed files 'input.{h,cc}' to 'input_api.{h,cc}'
- for "--input istream": moved input position increment to 'stmt_restorectx'
- main.cc: removed useless include
2015-01-13 15:30:01 +00:00
Ulya Trofimovich d9a03dd143 New input API.
- command-line switch "--input <default | istream | custom>"
- with "--input default" (the default) no changes to generated code
- with "--input istream" assume YYCURSOR is std::istream object
    and YYLIMIT is length of input stream
- with "--input custom" expose primitives:
    YYPEEK ()
    YYSKIP ()
    YYBACKUP ()
    YYBACKUPCTX ()
    YYRESTORE ()
    YYRESTORECTX ()
    YYHAS (n)
2015-01-11 19:39:32 +00:00
Ulya Trofimovich c41a3c3352 Added test for bug #46. 2014-09-26 22:35:28 +01:00
Ulya Trofimovich c4bbb17239 Added test for bug #47. 2014-09-26 22:23:54 +01:00
Ulya Trofimovich 94874fd70c Fixed bug #47: Dot output label escaped characters.
Double-escape special characters for dot.
Example:
    17 -> 18 [label="\n"]
results in an "unlabeled" arrow in the rendered graph, but
    17 -> 18 [label="\\n"]
is ok.
2014-09-26 17:14:20 +01:00
Ulya Trofimovich f432097a96 Removed outdated MSVC files, cleaned .gitignore 2014-09-26 16:15:49 +01:00
Ulya Trofimovich 410e370419 Back up re2c.1 manpage for those who build from git but don't have asciidoc. 2014-09-26 16:14:35 +01:00
Ulya Trofimovich eb8d21d301 Updated version to 0.13.8.dev 2014-09-24 12:09:31 +01:00
Ulya Trofimovich 29867e8462 Revert "Updated version to 0.13.6.dev"
This reverts commit bbb49c05b9.
2014-09-24 12:05:02 +01:00
Ulya Trofimovich bbb49c05b9 Updated version to 0.13.6.dev 2014-08-22 23:52:46 +03:00
Ulya Trofimovich 7713cfc158 Release 0.13.7.5. 2014-08-22 23:47:11 +03:00
Ulya Trofimovich 7205f9126b Alternation of 'RegExp's should preserve 'ins_access' attribute.
When one builds 'AltOp' from two 'RegExp's, one sometimes has to
break these 'RegExp's in pieces in order to merge their common prefix.
In such cases, if one of the original 'RegExp's has 'ins_access'
set to 'PRIVATE', it is lost (defaults to 'SHARED') after alternation.

This commit fixes Gentoo bug https://bugs.gentoo.org/show_bug.cgi?id=518904.
2014-08-22 23:15:11 +03:00
Ulya Trofimovich 15d77b1ab5 Replaced hand-written dynamic type introspection with dynamic_cast. 2014-08-22 23:07:05 +03:00
Ulya Trofimovich 90d8b2f4f5 Fixed typo in comment. 2014-08-21 13:48:33 +03:00
Ulya Trofimovich bdcf3dccec run_tests.sh: set locale "LC_ALL=C" for sed.
This fixes test failure on MacOS X.
2014-07-30 00:05:32 +03:00
Ulya Trofimovich ed0b7dbc14 release.sh: force directory removal 2014-07-29 18:17:55 +03:00
Ulya Trofimovich 0577a08064 Updated version to 0.13.7.5.dev 2014-07-29 18:17:10 +03:00
Ulya Trofimovich 0da106a7d0 Release 0.13.7.4. 2014-07-29 18:11:41 +03:00
Ulya Trofimovich dbbd75490e release.sh: don't forget to push as well as push tags 2014-07-29 18:08:07 +03:00
Ulya Trofimovich c370c2b064 release.sh: updated to use '--enable-docs' in configure 2014-07-29 18:07:07 +03:00
Ulya Trofimovich f5feb52402 release.sh: renamed configure.in -> configure.ac 2014-07-29 18:05:00 +03:00
Ulya Trofimovich f85cd0174e Enable 'make docs' only if configured with '--enable-docs'.
./configure --enable-docs checks for asciidoc and a2x
2014-07-29 17:53:49 +03:00
Ulya Trofimovich efab18a073 Disallow to use yacc/byacc instead of bison to build parser.
Currently parser fails to build with yacc/byacc.
A slightly modified parser, build by byacc, causes 3 tests to fail.
2014-07-29 14:59:08 +03:00
Ulya Trofimovich 76675fe3c9 Renamed configure.in -> configure.ac 2014-07-28 22:10:04 +03:00
Ulya Trofimovich 895f7a50ca Fixed compile error for freebsd5 (found by Sergei Trofimovich).
Sample error:
    parser.y: In function `void re2c::parse(re2c::Scanner&, std::ostream&, std::ostream*)':
    parser.y:564: error: `yyparse' undeclared (first use this function)
2014-07-28 18:57:49 +03:00
Ulya Trofimovich a43ddb4e09 run_tests.sh: avoid non-portable sed feature 2014-07-28 18:07:52 +03:00
Ulya Trofimovich e940d45be9 release.sh: clean tarball directory before rsync'ing to sourceforge
(shouldn't push old tarballs)
2014-07-28 18:05:22 +03:00
Ulya Trofimovich 539216c791 Update version to 0.13.7.4.dev 2014-07-28 18:03:34 +03:00
Ulya Trofimovich 965cb7ca1e Release 0.13.7.3. 2014-07-28 14:08:59 +03:00
Ulya Trofimovich 6f06336954 Got rid of asciidoc build-time dependency. 2014-07-28 13:58:36 +03:00
Ulya Trofimovich 37cd13ba7e Fixed compilation warning for clang.
Sample warning:
    warning: struct 'RegExp' was previously declared as a class [-Wmismatched-tags]
    struct RegExp; // forward
    ^
2014-07-28 11:41:19 +03:00
Ulya Trofimovich 7a1418856f Updated version to 0.13.8.dev. 2014-07-27 11:38:41 +03:00
5046 changed files with 2386935 additions and 620740 deletions

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
* text=auto
test/newlines/** -text
+99
View File
@@ -0,0 +1,99 @@
name: benchmarks
on:
# allow to trigger manually (on default branch)
workflow_dispatch:
# run once a week
schedule:
- cron: '0 0 * * 0'
defaults:
run:
shell: bash
jobs:
build-and-run:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
# Linux
- name: linux-gcc
os: ubuntu-latest
# macOS
- name: macos-clang
os: macos-latest
# no Windows, as Kleenex generates non-portable C code
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: '3.8'
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '11'
- name: Setup Common Prerequisites
run: |
case ${{ runner.os }} in
Linux*)
echo "CC=gcc" >> $GITHUB_ENV
echo "CXX=g++" >> $GITHUB_ENV
sudo apt update
sudo apt install libre2-dev libbenchmark-dev
;;
macOS*)
sudo xcode-select -switch /Applications/Xcode.app
echo "CC=$(xcrun -f clang)" >> $GITHUB_ENV
echo "CXX=$(xcrun -f clang++)" >> $GITHUB_ENV
echo "SDKROOT=$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_ENV
echo "$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_PATH
brew install re2 google-benchmark
;;
esac
pip install psutil
- name: Configure
run: |
cmake -S . -B .build \
-G "Unix Makefiles" \
-DRE2C_BUILD_LIBS=ON \
-DRE2C_BUILD_RE2GO=OFF \
-DRE2C_BUILD_RE2RUST=OFF \
-DRE2C_BUILD_BENCHMARKS=ON \
-DCMAKE_CXX_FLAGS="-O3"
- name: Build
run: cmake --build .build
- name: Run submatch DFA AOT benchmark
working-directory: .build/benchmarks/submatch_dfa_aot
run: |
./run.py --quickverify \
&& ./run.py --repetitions 5 --output results.json \
&& cat results.json
- name: Run submatch DFA JIT benchmark
working-directory: .build/benchmarks/submatch_dfa_jit
run: ./bench_submatch_dfa_jit
- name: Run submatch Java benchmark (ReTdfa)
working-directory: .build/benchmarks/submatch_java
run: ./run.py
- name: Run submatch NFA benchmark
working-directory: .build/benchmarks/submatch_nfa
run: ./bench_submatch_nfa
+158
View File
@@ -0,0 +1,158 @@
name: CI autotools
on:
push:
pull_request:
defaults:
run:
shell: bash
jobs:
build-and-test:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
# When set to true, GitHub cancels
# all in-progress jobs if any matrix job fails.
fail-fast: false
matrix:
include:
- name: linux-gcc-intree
os: ubuntu-latest
- name: linux-gcc-ootree
os: ubuntu-latest
# macOS
- name: macos-clang-intree
os: macos-latest
- name: macos-clang-ootree
os: macos-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup apt cache (Linux)
if: startsWith(runner.os, 'Linux')
uses: actions/cache@v3
with:
path: /var/cache/apt
key: ${{ runner.os }}-apt-cache-${{ matrix.os }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-apt-cache-${{ matrix.os }}-
${{ runner.os }}-apt-cache-
- name: Setup Common Prerequisites
run: |
case ${{ runner.os }} in
Linux*)
sudo apt update
sudo apt install autoconf automake libtool bison
;;
macOS*)
sudo xcode-select -switch /Applications/Xcode.app
echo "SDKROOT=$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_ENV
echo "$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_PATH
brew install autoconf automake libtool bison coreutils
# bison is not activated by default to avoid clobbering
# already present outdated system bison. Let's prepend
# brew's path.
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
;;
esac
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: 3.x
architecture: x64
- name: Install Python Dependencies
run: |
python -m pip install --upgrade pip
python -m pip install docutils pygments
- name: Generate ./configure
run: ./autogen.sh
- name: Fast Configure
run: |
./configure \
--disable-golang \
--disable-rust \
--prefix=$PWD/install
- name: Fast Build
run: make -j$(nproc)
- name: Fast Install
run: make -j$(nproc) install
- name: Fast Clean
run: make -j$(nproc) distclean
- name: Minimal Install Test
working-directory: ./install/bin
run: ./re2c --version
- name: Get build dir
id: build-info
run: |
if echo "${{ matrix.name }}" | grep -q "ootree"; then
BUILD_DIR="$(pwd)/.build/${{ matrix.name }}-full"
mkdir -p "$BUILD_DIR"
else
BUILD_DIR="$(pwd)"
fi
echo "BUILD_DIR=$BUILD_DIR" >> $GITHUB_OUTPUT
- name: Full Configure
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: |
$GITHUB_WORKSPACE/configure \
--prefix=$PWD/full-install \
--enable-libs \
--enable-parsers \
--enable-lexers \
--enable-docs \
--enable-debug \
RE2C_FOR_BUILD=$GITHUB_WORKSPACE/install/bin/re2c
- name: Full Build
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: |
find $GITHUB_WORKSPACE/src -name '*.re' | xargs touch
make -j$(nproc)
- name: Run Main Test Suite
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: bash -c "ulimit -s 256; make check -j$(nproc)"
- name: Run Skeleton Tests
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: python run_tests.py --skeleton
- name: Full Install
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: make -j$(nproc) install
- name: Archive test artifacts
# Run this step only if tests failed (otherwise there is nothing to upload).
if: failure()
uses: actions/upload-artifact@v3
with:
# To ensure that jobs don't overwrite existing artifacts,
# use a different name per job.
name: test-${{ matrix.name }}
# Tests run in a temporary directory that has a name test_<timestamp>.
path: ${{ steps.build-info.outputs.BUILD_DIR }}/test_[0-9]*
# Artifacts are retained for 90 days by default.
# In fact, we don't need such long period.
retention-days: 30
+177
View File
@@ -0,0 +1,177 @@
name: CI CMake
on:
push:
pull_request:
defaults:
run:
shell: bash
jobs:
build-and-test:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
# When set to true, GitHub cancels
# all in-progress jobs if any matrix job fails.
fail-fast: false
matrix:
include:
# Linux
- name: linux-gcc-ubsan-ootree
os: ubuntu-latest
- name: linux-gcc-asan-ootree
os: ubuntu-latest
- name: linux-gcc-valgrind-ootree
os: ubuntu-latest
- name: linux-gcc-debug-ootree-skeleton
os: ubuntu-latest
- name: linux-gcc-debug-intree-m32-skeleton
os: ubuntu-latest
- name: linux-gcc-release-ootree-skeleton
os: ubuntu-latest
# macOS
- name: macos-clang-debug-ootree-skeleton
os: macos-latest
- name: macos-clang-debug-intree-skeleton
os: macos-latest
- name: macos-clang-release-ootree-skeleton
os: macos-latest
# Windows
- name: windows-msvc-debug-ootree
os: windows-latest
- name: windows-msvc-debug-intree
os: windows-latest
- name: windows-msvc-release-ootree
os: windows-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup chocolatey Cache (Windows)
if: startsWith(runner.os, 'Windows')
uses: actions/cache@v3
with:
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
key: ${{ runner.os }}-chocolatey-${{ matrix.os }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-chocolatey-${{ matrix.os }}-
${{ runner.os }}-chocolatey-
- name: Setup apt cache (Linux)
if: startsWith(runner.os, 'Linux')
uses: actions/cache@v3
with:
path: /var/cache/apt
key: ${{ runner.os }}-apt-cache-${{ matrix.os }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-apt-cache-${{ matrix.os }}-
${{ runner.os }}-apt-cache-
- name: Setup Common Prerequisites
run: |
case ${{ runner.os }} in
Linux*)
sudo apt update
sudo apt install gcc-multilib g++-multilib # for -m32
sudo apt install valgrind
;;
macOS*)
sudo xcode-select -switch /Applications/Xcode.app
echo "SDKROOT=$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_ENV
echo "$(xcodebuild -version -sdk macosx Path)" >> $GITHUB_PATH
brew install coreutils # for `nproc`
;;
Windows*)
choco install --no-progress -y winflexbison3
choco install gnuwin32-coreutils.install # for `nproc`
;;
esac
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: 3.x
architecture: x64
- name: Install Python Dependencies
run: |
python -m pip install --upgrade pip
python -m pip install docutils pygments
- name: Check Available Configure Presets
run: cmake --list-presets
- name: Fast Configure
run: cmake --preset=${{ matrix.name }}-fast -DPython3_ROOT_DIR="${{ env.pythonLocation }}"
- name: Fast Build
run: cmake --build --preset=${{ matrix.name }}-fast -j$(nproc)
- name: Install
run: cmake --build --preset=${{ matrix.name }}-fast --target install
- name: Minimal Install Test
working-directory: ./install/bin
run: ./re2c --version
- name: Get build dir
id: build-info
run: |
if echo "${{ matrix.name }}" | grep -q "ootree"; then
BUILD_DIR="$(pwd)/.build/${{ matrix.name }}-full"
else
BUILD_DIR="$(pwd)"
fi
echo "BUILD_DIR=$BUILD_DIR" >> $GITHUB_OUTPUT
- name: Full Configure
run: cmake --preset=${{ matrix.name }}-full -DPython3_ROOT_DIR="${{ env.pythonLocation }}"
- name: Full Build
run: |
find src -name '*.re' | xargs touch
cmake --build --preset=${{ matrix.name }}-full -j$(nproc)
- name: Run Main Test Suite
run: bash -c "ulimit -s 256; cmake --build --preset=${{ matrix.name }}-full --target tests -j$(nproc)"
- name: Run Skeleton Tests
if: "contains(matrix.name, 'skeleton')"
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: python run_tests.py --skeleton
- name: Run Valgrind Tests
if: "contains(matrix.name, 'valgrind')"
working-directory: ${{ steps.build-info.outputs.BUILD_DIR }}
run: python run_tests.py --valgrind
- name: Archive test artifacts
# Run this step only if tests failed (otherwise there is nothing to upload).
if: failure()
uses: actions/upload-artifact@v3
with:
# To ensure that jobs don't overwrite existing artifacts,
# use a different name per job.
name: test-${{ matrix.name }}
# Tests run in a temporary directory that has a name test_<timestamp>.
path: ${{ steps.build-info.outputs.BUILD_DIR }}/test_[0-9]*
# Artifacts are retained for 90 days by default.
# In fact, we don't need such long period.
retention-days: 30
+31
View File
@@ -0,0 +1,31 @@
# Please do not use this ignore file to define platform specific files
# e.g. autogenerated files by IDE.
#
# For these purposes create a global .gitignore file, which is a list of rules
# for ignoring files in every Git repository on your computer.
#
# https://help.github.com/articles/ignoring-files/#create-a-global-gitignore
# The directories to ignore (do not add trailing '/'s, they skip symlinks).
/autom4te.cache
/m4
/test_*
/.build*
/bazel-*
# Ignore user defined CMake presets
CMakeUserPresets.json
# The files autogenerated by automake.
Makefile.in
aclocal.m4
configure
compile
config.h.in
config.guess
config.sub
depcomp
install-sh
ltmain.sh
missing
test-driver
+3
View File
@@ -0,0 +1,3 @@
[submodule "benchmarks/submatch_java/REgen"]
path = benchmarks/submatch_java/REgen
url = https://github.com/skvadrik/REgen.git
+84
View File
@@ -0,0 +1,84 @@
language: cpp
# use Ubuntu 20.04 (Focal Fossa) that defaults to Python 3
dist: focal
# speed up incremental builds
cache: ccache
compiler:
- gcc
- clang
# preinstalled packages
addons:
apt:
packages:
- bison
- python3-docutils
# configurations: cmake/autotools, in-tree/out-of-tree, release/debug, etc.
env:
- CMAKE=no BUILD_DIR=. CONFIG_DIR=. COMMON_FLAGS="-O2 -g"
- CMAKE=no BUILD_DIR=.build CONFIG_DIR=.. CONFIG_FLAGS="--enable-debug" COMMON_FLAGS="-O2 -g"
- CMAKE=yes BUILD_DIR=. CONFIG_DIR=. BUILD_TYPE=Debug COMMON_FLAGS="-O2 -g"
- CMAKE=yes BUILD_DIR=.build CONFIG_DIR=.. BUILD_TYPE=Debug COMMON_FLAGS="-O2 -g" SKELETON=yes
- CMAKE=yes BUILD_DIR=.build CONFIG_DIR=.. BUILD_TYPE=Release
- CMAKE=yes BUILD_DIR=.build CONFIG_DIR=.. BUILD_TYPE=Debug COMMON_FLAGS="-O2 -g -fsanitize=address"
- CMAKE=yes BUILD_DIR=.build CONFIG_DIR=.. BUILD_TYPE=Debug COMMON_FLAGS="-O2 -g -fsanitize=undefined"
script:
- |
function run_cmake() {
cmake \
-B . -S ${CONFIG_DIR} \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DCMAKE_C_FLAGS="${COMMON_FLAGS}" \
-DCMAKE_CXX_FLAGS="${COMMON_FLAGS}" \
-DCMAKE_EXE_LINKER_FLAGS="${COMMON_FLAGS}" \
-DCMAKE_SHARED_LINKER_FLAGS="${COMMON_FLAGS}" \
$@
}
function run_configure() {
${CONFIG_DIR}/configure \
${CONFIG_FLAGS} \
CFLAGS="${COMMON_FLAGS}" \
CXXFLAGS="${COMMON_FLAGS}" \
LDFLAGS="${COMMON_FLAGS}" \
$@
}
- |
if [ x${CMAKE} = "xyes" ]; then
mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
run_cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
else
./autogen.sh
mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
run_configure --prefix="$(pwd)/install"
fi
- make -j$(nproc)
- make install
- |
if [ x${CMAKE} = "xyes" ]; then
run_cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install-2" \
-DRE2C_BUILD_RE2GO=on \
-DRE2C_BUILD_LIBS=on \
-DRE2C_REBUILD_DOCS=on \
-DRE2C_REBUILD_LEXERS=on \
-DRE2C_FOR_BUILD="$(pwd)/install/bin/re2c"
else
run_configure --prefix="$(pwd)/install-2" \
--enable-golang \
--enable-libs \
--enable-docs \
--enable-lexers \
RE2C_FOR_BUILD="$(pwd)/install/bin/re2c"
fi
- find ${CONFIG_DIR}/src -name '*.re' | xargs touch
- make -j$(nproc)
- |
if [ x${SKELETON} = "xyes" ]; then
./run_tests.py --skeleton
else
make -j$(nproc) check VERBOSE=1
fi
+45
View File
@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:private"])
genrule(
name = "re2c_config",
srcs = [
"CMakeLists.txt",
"//bazel:re2c_config.h",
],
outs = ["config.h"],
cmd = """
cat $(location //:CMakeLists.txt) |\\
sed -rne 's/project\\(re2c VERSION ([^ ]+).*/#define PACKAGE_VERSION "\\1-bootstrap"/p' >> "$@"
cat $(location //bazel:re2c_config.h) >> "$@"
""",
)
cc_library(
name = "re2c_config_cc",
hdrs = ["config.h"],
defines = ["""RE2C_STDLIB_DIR='"$(BINDIR)/re2c.runfiles/re2c/include"'"""],
data = ["include/unicode_categories.re"],
)
cc_library(
name = "re2c_bootstrap_cc",
includes = ["bootstrap"],
hdrs = glob([
"bootstrap/src/**/*.h",
"src/**/*.h",
]),
srcs = glob([
"bootstrap/src/**/*.cc",
"src/**/*.cc",
]),
deps = [
"re2c_config_cc", # Needed for 're2c_config_cc' data files
],
)
cc_binary(
name = "re2c",
srcs = ["src/main.cc"],
deps = [":re2c_bootstrap_cc"],
visibility = ["//visibility:public"],
)
+226
View File
@@ -0,0 +1,226 @@
How to build
============
Dependencies
------------
To build re2c from a release tarball one needs only a C++ compiler (supporting
at least C++11) and Python 3 for build-time scripts and for testing. Building on
Windows additionally requires either CMake or a Mingw build environment.
To develop re2c one also needs CMake or Autotools (both build systems are
maintained). Other dependencies include Bison (to rebuild parsers), Python 3
Docutils (to rebuild documentation) and Sphinx (to rebuild the website).
Benchmarks also use Google-benchmark, re2 and Java. A few helper scripts are
written in Haskell, but they are not essential for re2c development.
re2c is a self-hosting lexer generator, meaning that parts of its source code
are written in re2c (namely, all the source files that have a *.re* extension).
By default re2c builds from pre-generated bootstrap files. To build from source
*.re* files, it is necessary to reconfigure the build and provide a path to an
existing re2c binary that will be used for bootstrap (see the details below).
Build (Autotools)
-----------------
If you are building from a release tarball, the configure script is already
there. Otherwise it is necessary to generate it:
```
$ autoreconf -i -W all
```
An in-tree build (objects are generated side by side with sources):
```
$ ./configure && make && make install
```
An out-of-tree build (objects are generated in a separate directory):
```
$ mkdir .build && cd .build && ../configure && make && make install
```
The configure script has many options (to see them all, run
`configure --help`). The options specific to re2c are the following:
* `--enable-debug`
Enable debug checks in the re2c source code. Also enables debug options.
* `--enable-golang`
Build re2go (identical to `re2c --lang go`). This is on by default.
* `--enable-rust`
Build re2rust (identical to `re2c --lang rust`). This is on by default.
* `--enable-lexers`
Enable regeneration of lexers from *.re* files (as opposed to using
pre-generated bootstrap files). This requires setting `RE2C_FOR_BUILD` to
an existing re2c executable path.
* `--enable-parsers`
Enable regeneration of parsers from *.ypp* files with bison (as opposed to
using pre-generated bootstrap files).
* `--enable-docs`
Enable regeneration of documentation (requires Python 3 Docutils).
* `--enable-benchmarks`
Build benchmarks (requires Google benchmarks library).
* `--enable-benchmarks-regenerate`
Regenerate C code for Ragel and Kleenex benchmarks (this will download and
build Ragel and Kleenex). re2c benchmarks are always regenerated.
* `--enable-libs`
Build the experimental libre2c library that provides POSIX
`regcomp`/`regexec`/`regfree` interface to re2c.
Cross-compile re2c for Windows (for some Mingw versions you might have to use
`-std=gnu++11` compiler option):
```
$ ./configure --host i686-w64-ming32 \
LDFLAGS="-static -static-libstdc++ -static-libgcc"
```
There is a bunch of build scripts for specialized builds with Asan, Ubsan,
GLIBCXX_DEBUG, etc. in the ``build`` subdirectory.
Build (CMake)
-------------
re2c includes CMake presets for Linux, MacOS, and Windows. Use `cmake
--list-presets` to see them.
* The `-fast` presets have minimal dependencies and build re2c using
pre-generated manpages, lexers, and parsers.
* The `-full` presets have additional prerequisites (Docutils, Bison, and a
pre-existing re2c binary) and re-generate the manpages, lexers, and parsers.
If you just want to build re2c, use the `-release-ootree-fast` preset. The
other presets are primarily of interest to developers.
For example, to build the `windows-msvc-release-ootree-fast` preset:
* CD to the root of the re2c folder (the folder containing this README).
* Configure: `cmake --preset=windows-msvc-release-ootree-fast`
* Build: `cmake --build --preset=windows-msvc-release-ootree-fast`
* The binary will be in the `.build/<preset-name>` folder.
CMake supports different build modes, which can be further customized with
individual options. By default re2c builds with `-O2 -g` and does not set any
particular mode to allow the user complete freedom in overriding the build
options. To enable a build mode at configure phase, use
`-DCMAKE_BUILD_TYPE=<mode>` option (this works with single-config generators,
such as Makefiles or Ninja). At build phase use `--config <mode>` option.
The following modes are supported:
* `Release`
This is an optimized `-O3 -DNDEBUG` build without debug symbols, asserts
and debug checks.
* `Debug`
This is a non-optimized `-g -DRE2C_DEBUG` build with debug symbols, asserts,
and debug checks.
* `RelWithDebInfo`
This is an optimized `-O2 -g -DNDEBUG` build with debug symbols, but
without asserts and debug checks.
* `MinSizeRel`
This is an optimized for size `-Os -DNDEBUG` build without debug symbols,
asserts and debug checks.
* `Asan`
This is a non-optimized `-g -fsanitize=address` build that instruments the
code with Address Sanitizer to check for memory errors.
* `Ubsan`
This is a non-optimized `-g -fsanitize=undefined` build that instruments
the code with Undefined Behavior Sanitizer to check for undefined behavior
errors.
A simple build (objects are generated in a separate build directory):
```
$ mkdir .build && cd .build && cmake .. && cmake --build .
```
CMake supports a lot of configuration options. Here is the list of options
specific to re2c:
* `-DRE2C_BUILD_RE2GO=yes`
Build re2go executable (an alias to `re2c --lang go`). Enabled by default.
* `-DRE2C_BUILD_RE2RUST=yes`
Build re2rust executable (an alias to `re2c --lang rust`). Enabled by
default.
* `-DRE2C_REBUILD_LEXERS=yes`
Enable regeneration of lexers from *.re* files (as opposed to using
pre-generated bootstrap files). This requires setting `-DRE2C_FOR_BUILD` to
an existing re2c executable path.
* `-DRE2C_REBUILD_PARSERS=yes`
Enable regeneration of parsers from *.ypp* files with bison (as opposed to
using pre-generated bootstrap files).
* `-DRE2C_REBUILD_DOCS=yes`
Enable regeneration of documentation (requires Python 3 Docutils).
* `-DRE2C_BUILD_BENCHMARKS=yes`
Build benchmarks (requires Google benchmarks library).
* `-DRE2C_REGEN_BENCHMARKS=yes`
Regenerate C code for Ragel and Kleenex benchmarks (this will download and
build Ragel and Kleenex). re2c benchmarks are always regenerated.
* `-DRE2C_BUILD_LIBS=yes`
Build the experimental libre2c library that provides POSIX
`regcomp`/`regexec`/`regfree` interface to re2c.
Cross-compile re2c for Windows using Mingw:
```
$ cmake . -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-cross-mingw32-linux.cmake \
-DCMAKE_EXE_LINKER_FLAGS="-static -static-libstdc++ -static-libgcc" \
-DBUILD_SHARED_LIBS=no
```
There is a bunch of build scripts for specialized builds with Asan, Ubsan,
GLIBCXX_DEBUG, etc. in the ``build`` subdirectory.
Test
----
re2c has a main test suite and a number of unit tests. Run them all:
```
$ make check
```
Run only the main test suite and watch the progress dumped on stdout:
```
$ python3 run_tests.py -j<N>
```
Run the main test suite with `--skeleton` re2c option:
```
$ python3 run_tests.py --skeleton
```
Run the test suite under Valgrind (takes some time and memory):
```
$ python3 run_tests.py --valgrind
```
Test Mingw builds with Wine:
```
$ make wtests
```
Check the distribution (works with Autotools):
```
$ make distcheck
```
re2c provides a helper script `build/__alltest.sh` that builds and tests various
re2c build flavours with Asan, Ubsan, GLIBCXX_DEBUG, etc. There is a couple of
fuzz-testing Haskell scripts in the *fuzz* subdirectory; they are based on the
QuickCheck library and can be easily modified to fuzz-test various aspects of
re2c by comparing current re2c version against older versions or against other
regular expression libraries.
+1552
View File
File diff suppressed because it is too large. Load diff
+538
View File
@@ -0,0 +1,538 @@
cmake_minimum_required(VERSION 3.12)
project(re2c VERSION 3.1 HOMEPAGE_URL "https://re2c.org/")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(Re2cAutotoolsHelpers)
include(Re2cBootstrapLexer)
include(Re2cBootstrapParser)
include(Re2cBuildType)
include(Re2cGenDocs)
include(Re2cCompilerFlags)
ac_subst(PACKAGE_VERSION "${PROJECT_VERSION}")
option(RE2C_REBUILD_LEXERS "Regenerate lexers" OFF)
if(RE2C_REBUILD_LEXERS AND NOT RE2C_FOR_BUILD)
message(FATAL_ERROR "option RE2C_FOR_BUILD is required for RE2C_REBUILD_LEXERS")
endif()
option(RE2C_REBUILD_PARSERS "Regenerate parsers with Bison" OFF)
if(RE2C_REBUILD_PARSERS AND NOT RE2C_FOR_BUILD)
find_package(BISON REQUIRED)
endif()
option(RE2C_REBUILD_DOCS "Regenerate manpage" OFF)
option(RE2C_BUILD_LIBS "Build libraries" OFF)
option(RE2C_BUILD_RE2GO "Build re2go executable (an alias for `re2c --lang go`)" ON)
option(RE2C_BUILD_RE2RUST "Build re2rust executable (an alias for `re2c --lang rust`)" ON)
option(RE2C_BUILD_BENCHMARKS "Build benchmarks" OFF)
option(RE2C_REGEN_BENCHMARKS "Regenerate C code for benchmarks" OFF)
# checks for programs
find_package(Python3 COMPONENTS Interpreter)
# starting from cmake 3.19 find_package can do version check, but we are on 3.12
if(Python3_VERSION VERSION_LESS 3.7)
message(FATAL_ERROR "python version 3.7 or higher is required")
endif()
if(RE2C_REBUILD_DOCS)
execute_process(
COMMAND "${Python3_EXECUTABLE}" -c "import docutils"
RESULT_VARIABLE EXIT_CODE
OUTPUT_QUIET
)
if (NOT ${EXIT_CODE} EQUAL 0)
message(FATAL_ERROR "python package docutils (needed for docs) not found")
endif()
endif()
# Use C++11 standard. Note that without `set(CMAKE_CXX_EXTENSIONS OFF)` this enables
# -std=gnu++11, not -std=c++11. Extensions are needed to enable POSIX functions on
# Cygwin and NetBSD.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # fail if the C++ compiler does not support this standard
set(CMAKE_POSITION_INDEPENDENT_CODE ON) # make sure object libraries work with shared libraries
# needed for POSIX file API
ac_check_headers("sys/types.h")
ac_check_headers("sys/stat.h")
ac_check_headers("fcntl.h")
ac_check_headers("unistd.h")
# windows POSIX-like API
ac_check_headers("io.h")
# docs (manpages and help)
set(re2c_manpage_source "${CMAKE_CURRENT_BINARY_DIR}/doc/manpage.rst")
set(re2c_help_source "${CMAKE_CURRENT_BINARY_DIR}/doc/help.rst")
set(re2c_manpage_bootstrap_c "${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/doc/re2c.1")
set(re2c_manpage_bootstrap_go "${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/doc/re2go.1")
set(re2c_manpage_bootstrap_rust "${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/doc/re2rust.1")
set(re2c_help_bootstrap "${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src/msg/help.cc")
set(re2c_manpage_c "${CMAKE_CURRENT_BINARY_DIR}/doc/re2c.1")
set(re2c_manpage_go "${CMAKE_CURRENT_BINARY_DIR}/doc/re2go.1")
set(re2c_manpage_rust "${CMAKE_CURRENT_BINARY_DIR}/doc/re2rust.1")
set(re2c_help "${CMAKE_CURRENT_BINARY_DIR}/src/msg/help.cc")
set(re2c_rst2man "${CMAKE_CURRENT_SOURCE_DIR}/build/rst2man.py")
set(re2c_rst2txt "${CMAKE_CURRENT_SOURCE_DIR}/build/rst2txt.py")
set(re2c_splitman "${CMAKE_CURRENT_SOURCE_DIR}/build/split_man.py")
set(re2c_docs
"${re2c_help}"
"${re2c_manpage_c}"
"$<$<BOOL:${RE2C_BUILD_RE2GO}>:${re2c_manpage_go}>"
"$<$<BOOL:${RE2C_BUILD_RE2RUST}>:${re2c_manpage_rust}>"
)
set(top_srcdir "${CMAKE_CURRENT_SOURCE_DIR}")
set(top_builddir "${CMAKE_CURRENT_BINARY_DIR}")
set(PYTHON "${Python3_EXECUTABLE}")
configure_file(doc/manpage.rst.in doc/manpage.rst @ONLY)
configure_file(doc/help.rst.in doc/help.rst @ONLY)
configure_file(run_tests.py.in run_tests.py @ONLY)
set(RE2C_RUN_TESTS "${CMAKE_CURRENT_BINARY_DIR}/run_tests.py")
if(CMAKE_HOST_UNIX)
execute_process(COMMAND chmod +x "${RE2C_RUN_TESTS}")
endif()
ac_config_headers("config.h")
# Makefile.am
set(RE2C_STDLIB_DIR "${CMAKE_INSTALL_PREFIX}/share/re2c/stdlib")
add_compile_definitions(
"RE2C_STDLIB_DIR=\"${RE2C_STDLIB_DIR}\""
$<$<CONFIG:Debug>:RE2C_DEBUG>
)
include_directories(. "${CMAKE_CURRENT_BINARY_DIR}")
# Build autogenerated sources into an object library to ensure that they are
# generated once at the beginning of build (as with Automake BUILT_SOURCES).
# WARNING: custom target that depends on autogenerated sources won't do here
# as its dependencies get built multiple times, which ruins parallel builds.
add_library(re2c_objects_autogen OBJECT
"${CMAKE_CURRENT_BINARY_DIR}/src/parse/parser.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/parse/parser.h"
"${CMAKE_CURRENT_BINARY_DIR}/src/parse/lex.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/parse/lex.h"
"${CMAKE_CURRENT_BINARY_DIR}/src/parse/lex_conf.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/options/parse_opts.cc"
"${re2c_docs}"
)
add_library(re2c_objects_autogen_ver_to_vernum OBJECT
"${CMAKE_CURRENT_BINARY_DIR}/src/msg/ver_to_vernum.cc"
)
set(re2c_sources
src/codegen/helpers.cc
src/codegen/output.cc
src/codegen/pass1_analyze.cc
src/codegen/pass2_generate.cc
src/codegen/pass3_fixup.cc
src/codegen/pass4_render.cc
src/options/opt.cc
src/options/symtab.cc
src/nfa/re_to_nfa.cc
src/adfa/adfa.cc
src/debug/dump_adfa.cc
src/debug/dump_cfg.cc
src/debug/dump_dfa.cc
src/debug/dump_dfa_tree.cc
src/debug/dump_interf.cc
src/debug/dump_nfa.cc
src/cfg/cfg.cc
src/cfg/compact.cc
src/cfg/dce.cc
src/cfg/freeze.cc
src/cfg/interfere.cc
src/cfg/liveanal.cc
src/cfg/normalize.cc
src/cfg/optimize.cc
src/cfg/rename.cc
src/cfg/varalloc.cc
src/dfa/closure.cc
src/dfa/dead_rules.cc
src/dfa/determinization.cc
src/dfa/fallback_tags.cc
src/dfa/fillpoints.cc
src/dfa/find_state.cc
src/dfa/minimization.cc
src/dfa/tagver_table.cc
src/dfa/tcmd.cc
src/encoding/ebcdic.cc
src/encoding/enc.cc
src/encoding/range_suffix.cc
src/encoding/utf8.cc
src/encoding/utf16.cc
src/msg/msg.cc
src/msg/warn.cc
src/regexp/ast_to_re.cc
src/regexp/default_tags.cc
src/regexp/fixed_tags.cc
src/regexp/nullable.cc
src/regexp/regexp.cc
src/regexp/split_charset.cc
src/skeleton/control_flow.cc
src/skeleton/generate_code.cc
src/skeleton/generate_data.cc
src/skeleton/maxpath.cc
src/skeleton/skeleton.cc
src/parse/ast.cc
src/parse/input.cc
src/util/file_utils.cc
src/util/string_utils.cc
src/util/range.cc
src/main.cc
$<TARGET_OBJECTS:re2c_objects_autogen>
$<TARGET_OBJECTS:re2c_objects_autogen_ver_to_vernum>
)
# re2c
add_executable(re2c ${re2c_sources})
# re2go
if (RE2C_BUILD_RE2GO)
add_executable(re2go ${re2c_sources})
target_compile_definitions(re2go PUBLIC "RE2C_LANG=Lang::GO")
endif()
# re2rust
if (RE2C_BUILD_RE2RUST)
add_executable(re2rust ${re2c_sources})
target_compile_definitions(re2rust PUBLIC "RE2C_LANG=Lang::RUST")
endif()
re2c_bootstrap_lexer("src/parse/lex.re" "src/parse/lex.cc" "src/parse/lex.h")
re2c_bootstrap_lexer("src/parse/lex_conf.re" "src/parse/lex_conf.cc")
re2c_bootstrap_lexer("src/options/parse_opts.re" "src/options/parse_opts.cc")
re2c_bootstrap_lexer("src/msg/ver_to_vernum.re" "src/msg/ver_to_vernum.cc")
re2c_bootstrap_parser("src/parse/parser.ypp" "src/parse/parser.cc" "src/parse/parser.h")
# docs
set(re2c_docs_sources
"${re2c_manpage_source}"
"doc/manual/api/interface.rst_"
"doc/manual/conditions/blocks.rst_"
"doc/manual/conditions/conditions.rst_"
"doc/manual/configurations/configurations.rst_"
"doc/manual/directives/directives.rst_"
"doc/manual/dot/dot.rst_"
"doc/manual/encodings/encodings.rst_"
"doc/manual/eof/01_sentinel.rst_"
"doc/manual/eof/02_bounds_checking.rst_"
"doc/manual/eof/03_eof_rule.rst_"
"doc/manual/eof/04_generic_api.rst_"
"doc/manual/eof/eof.rst_"
"doc/manual/fill/01_fill.rst_"
"doc/manual/fill/02_fill.rst_"
"doc/manual/fill/fill.rst_"
"doc/manual/headers/headers.rst_"
"doc/manual/includes/includes.rst_"
"doc/manual/options/debug.rst_"
"doc/manual/options/internal.rst_"
"doc/manual/options/options.rst_"
"doc/manual/regexps/regular_expressions.rst_"
"doc/manual/reuse/reuse.rst_"
"doc/manual/skeleton/skeleton.rst_"
"doc/manual/state/state.rst_"
"doc/manual/submatch/submatch_example_mtags.rst_"
"doc/manual/submatch/submatch_example_posix.rst_"
"doc/manual/submatch/submatch_example_stags_fill.rst_"
"doc/manual/submatch/submatch_example_stags.rst_"
"doc/manual/submatch/submatch.rst_"
"doc/manual/synopsis.rst_"
"doc/manual/syntax/api1.rst_"
"doc/manual/syntax/api2_c.rst_"
"doc/manual/syntax/api2_go.rst_"
"doc/manual/syntax/api2_rust.rst_"
"doc/manual/syntax/api3.rst_"
"doc/manual/syntax/intro.rst_"
"doc/manual/syntax/syntax.rst_"
"doc/manual/warnings/warnings_general.rst_"
"doc/manual/warnings/warnings_list.rst_"
"examples/c/01_basic.re"
"examples/c/01_basic.c"
"examples/c/conditions/parse_u32_blocks.re"
"examples/c/conditions/parse_u32_conditions.re"
"examples/c/encodings/unicode_identifier.re"
"examples/c/eof/01_sentinel.re"
"examples/c/eof/02_bounds_checking.re"
"examples/c/eof/03_eof_rule.re"
"examples/c/eof/05_generic_api_eof_rule.re"
"examples/c/fill/01_fill.re"
"examples/c/fill/02_fill.re"
"examples/c/headers/header.re"
"examples/c/headers/lexer/state.h"
"examples/c/includes/include.re"
"examples/c/includes/definitions.h"
"examples/c/reuse/reuse.re"
"examples/c/reuse/usedir.re"
"examples/c/state/push.re"
"examples/c/submatch/01_stags_fill.re"
"examples/c/submatch/01_stags.re"
"examples/c/submatch/02_mtags.re"
"examples/c/submatch/03_posix.re"
"examples/go/01_basic.re"
"examples/go/01_basic.go"
"examples/go/conditions/parse_u32_blocks.re"
"examples/go/conditions/parse_u32_conditions.re"
"examples/go/encodings/unicode_identifier.re"
"examples/go/eof/01_sentinel.re"
"examples/go/eof/02_bounds_checking.re"
"examples/go/eof/03_eof_rule.re"
"examples/go/eof/05_generic_api_eof_rule.re"
"examples/go/fill/01_fill.re"
"examples/go/fill/02_fill.re"
"examples/go/headers/header.re"
"examples/go/headers/lexer/state.go"
"examples/go/includes/include.re"
"examples/go/includes/definitions.go"
"examples/go/reuse/reuse.re"
"examples/go/reuse/usedir.re"
"examples/go/state/push.re"
"examples/go/submatch/01_stags_fill.re"
"examples/go/submatch/01_stags.re"
"examples/go/submatch/02_mtags.re"
"examples/go/submatch/03_posix.re"
"examples/rust/01_basic.re"
"examples/rust/01_basic.rs"
"examples/rust/conditions/parse_u32_blocks.re"
"examples/rust/conditions/parse_u32_conditions.re"
"examples/rust/encodings/unicode_identifier.re"
"examples/rust/eof/01_sentinel.re"
"examples/rust/eof/02_bounds_checking.re"
"examples/rust/eof/03_eof_rule.re"
"examples/rust/eof/05_generic_api_eof_rule.re"
"examples/rust/fill/01_fill.re"
"examples/rust/fill/02_fill.re"
"examples/rust/headers/header.re"
"examples/rust/headers/lexer/state.rs"
"examples/rust/includes/include.re"
"examples/rust/includes/definitions.rs"
"examples/rust/reuse/reuse.re"
"examples/rust/reuse/usedir.re"
"examples/rust/state/push.re"
"examples/rust/submatch/01_stags_fill.re"
"examples/rust/submatch/01_stags.re"
"examples/rust/submatch/02_mtags.re"
"examples/rust/submatch/03_posix.re"
)
re2c_gen_manpage("${re2c_manpage_source}" "${re2c_manpage_c}" "${re2c_manpage_bootstrap_c}" "c")
re2c_gen_manpage("${re2c_manpage_source}" "${re2c_manpage_go}" "${re2c_manpage_bootstrap_go}" "go")
re2c_gen_manpage("${re2c_manpage_source}" "${re2c_manpage_rust}" "${re2c_manpage_bootstrap_rust}" "rust")
re2c_gen_help("${re2c_help_source}" "${re2c_help}" "${re2c_help_bootstrap}")
add_custom_target(docs DEPENDS "${re2c_docs}")
# install and test targets are enabled only if re2c is the root project
if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
# install
install(TARGETS re2c RUNTIME DESTINATION bin)
install(FILES "${re2c_manpage_c}" DESTINATION "share/man/man1")
if(RE2C_BUILD_RE2GO)
install(TARGETS re2go RUNTIME DESTINATION bin)
install(FILES "${re2c_manpage_go}" DESTINATION "share/man/man1")
endif()
if(RE2C_BUILD_RE2RUST)
install(TARGETS re2rust RUNTIME DESTINATION bin)
install(FILES "${re2c_manpage_rust}" DESTINATION "share/man/man1")
endif()
install(FILES include/unicode_categories.re DESTINATION "${RE2C_STDLIB_DIR}")
# rebuild all re2c sources using newly built re2c
add_custom_target(bootstrap
COMMAND "${CMAKE_COMMAND}" -E remove_directory "src"
COMMAND "${CMAKE_COMMAND}" -E remove_directory "doc"
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}"
)
# tests
add_custom_target(tests
DEPENDS "${RE2C_RUN_TESTS}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMAND "${Python3_EXECUTABLE}" "${RE2C_RUN_TESTS}"
)
add_dependencies(tests re2c)
add_custom_target(vtests
DEPENDS "${RE2C_RUN_TESTS}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMAND "${Python3_EXECUTABLE}" "${RE2C_RUN_TESTS}" --valgrind
)
add_dependencies(vtests re2c)
add_custom_target(wtests
DEPENDS "${RE2C_RUN_TESTS}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMAND "${Python3_EXECUTABLE}" "${RE2C_RUN_TESTS}" --wine -j1
)
add_dependencies(wtests re2c)
add_executable(re2c_test_range
src/test/range/test-impl.h
src/test/range/test.cc
src/test/range/test.h
src/util/range.cc
src/util/range.h
)
add_executable(re2c_test_s_to_n32_unsafe
src/test/s_to_n32_unsafe/test.cc
src/util/string_utils.cc
)
add_executable(re2c_test_ver_to_vernum
src/test/ver_to_vernum/test.cc
$<TARGET_OBJECTS:re2c_objects_autogen_ver_to_vernum>
)
add_executable(re2c_test_argsubst
src/test/argsubst/test.cc
src/codegen/helpers.cc
)
add_custom_target(check_re2c
COMMAND ./re2c_test_range
COMMAND ./re2c_test_s_to_n32_unsafe
COMMAND ./re2c_test_ver_to_vernum
COMMAND ./re2c_test_argsubst
)
add_dependencies(check_re2c
tests
re2c_test_range
re2c_test_s_to_n32_unsafe
re2c_test_ver_to_vernum
re2c_test_argsubst
)
endif()
if (RE2C_BUILD_LIBS)
# Build autogenerated sources into an object library to ensure that they are
# generated once at the beginning of build (as with Automake BUILT_SOURCES).
# WARNING: custom target that depends on autogenerated sources won't do here
# as its dependencies get built multiple times, which ruins parallel builds.
add_library(libre2c_objects_autogen OBJECT
"${CMAKE_CURRENT_BINARY_DIR}/lib/lex.cc"
"${CMAKE_CURRENT_BINARY_DIR}/lib/parse.cc"
)
re2c_bootstrap_lexer("lib/lex.re" "lib/lex.cc")
re2c_bootstrap_parser("lib/parse.ypp" "lib/parse.cc" "lib/parse.h")
add_library(test_libre2c_objects_autogen OBJECT
"${CMAKE_CURRENT_BINARY_DIR}/lib/test_helper.cc"
)
re2c_bootstrap_lexer("lib/test_helper.re" "lib/test_helper.cc")
set(libre2c_sources
lib/regcomp.cc
lib/regexec.cc
lib/regexec_dfa.cc
lib/regexec_dfa_multipass.cc
lib/regexec_nfa_leftmost.cc
lib/regexec_nfa_leftmost_trie.cc
lib/regexec_nfa_posix.cc
lib/regexec_nfa_posix_trie.cc
lib/regfree.cc
lib/stubs.cc
src/parse/ast.cc
src/parse/input.cc
src/options/opt.cc
src/options/symtab.cc
src/cfg/cfg.cc
src/cfg/compact.cc
src/cfg/dce.cc
src/cfg/freeze.cc
src/cfg/interfere.cc
src/cfg/liveanal.cc
src/cfg/normalize.cc
src/cfg/optimize.cc
src/cfg/rename.cc
src/cfg/varalloc.cc
src/dfa/closure.cc
src/debug/dump_adfa.cc
src/debug/dump_cfg.cc
src/debug/dump_dfa.cc
src/debug/dump_dfa_tree.cc
src/debug/dump_interf.cc
src/debug/dump_nfa.cc
src/dfa/dead_rules.cc
src/dfa/determinization.cc
src/dfa/fallback_tags.cc
src/dfa/fillpoints.cc
src/dfa/find_state.cc
src/dfa/minimization.cc
src/dfa/tagver_table.cc
src/dfa/tcmd.cc
src/nfa/re_to_nfa.cc
src/encoding/enc.cc
src/encoding/range_suffix.cc
src/encoding/ebcdic.cc
src/encoding/utf16.cc
src/encoding/utf8.cc
src/msg/msg.cc
src/msg/warn.cc
src/regexp/ast_to_re.cc
src/regexp/default_tags.cc
src/regexp/fixed_tags.cc
src/regexp/nullable.cc
src/regexp/regexp.cc
src/regexp/split_charset.cc
src/skeleton/control_flow.cc
src/skeleton/maxpath.cc
src/skeleton/skeleton.cc
src/util/range.cc
src/util/file_utils.cc
src/util/string_utils.cc
$<TARGET_OBJECTS:libre2c_objects_autogen>
$<TARGET_OBJECTS:re2c_objects_autogen_ver_to_vernum>
)
# on Windows add suffix to static libs to avoid collision of .lib files with shared libs
set(RE2C_STATIC_LIB_SFX "$<$<PLATFORM_ID:Windows>:_static>")
# build static libraries
if ((NOT DEFINED BUILD_SHARED_LIBS) OR (NOT BUILD_SHARED_LIBS))
add_library(libre2c_static STATIC ${libre2c_sources})
set_target_properties(libre2c_static PROPERTIES OUTPUT_NAME "re2c${RE2C_STATIC_LIB_SFX}")
if (UNIX)
install(TARGETS libre2c_static ARCHIVE DESTINATION lib)
endif()
endif()
# build shared libraries
if ((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS)
add_library(libre2c_shared SHARED ${libre2c_sources})
set_target_properties(libre2c_shared PROPERTIES OUTPUT_NAME "re2c")
if (UNIX)
install(TARGETS libre2c_shared LIBRARY DESTINATION lib)
endif()
endif()
# define top-level aliases to either static or shared libraries (default is static)
if (BUILD_SHARED_LIBS)
add_library(libre2c ALIAS libre2c_shared)
else()
add_library(libre2c ALIAS libre2c_static)
endif()
# libre2c test
add_executable(test_libre2c lib/test.cc)
target_link_libraries(test_libre2c libre2c)
target_link_libraries(test_libre2c test_libre2c_objects_autogen)
add_custom_target(check_libre2c
COMMAND ./test_libre2c
)
if(RE2C_BUILD_BENCHMARKS)
add_subdirectory(benchmarks/submatch_nfa)
add_subdirectory(benchmarks/submatch_dfa_jit)
add_subdirectory(benchmarks/submatch_java)
endif()
else()
# empty check target
add_custom_target(check_libre2c)
endif()
if(RE2C_BUILD_BENCHMARKS)
add_subdirectory(benchmarks/submatch_dfa_aot)
endif()
# only add check target if toplevel project
if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
add_custom_target(check)
add_dependencies(check check_re2c check_libre2c)
endif()
+498
View File
@@ -0,0 +1,498 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 1
},
"configurePresets": [
{
"name": "default-full-configuration",
"hidden": true,
"installDir": "${sourceDir}/install-2",
"cacheVariables": {
"RE2C_BUILD_RE2GO": true,
"RE2C_BUILD_RE2RUST": true,
"RE2C_BUILD_LIBS": true,
"RE2C_REBUILD_LEXERS": true,
"RE2C_REBUILD_DOCS": true,
"RE2C_FOR_BUILD": "${sourceDir}/install/bin/re2c"
}
},
{
"name": "linux-config-base",
"hidden": true,
"generator": "Unix Makefiles",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc",
"CMAKE_CXX_COMPILER": "g++"
}
},
{
"name": "linux-gcc-ubsan-ootree-fast",
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (fast)",
"inherits": "linux-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Ubsan",
"CMAKE_C_FLAGS": "-O2",
"CMAKE_CXX_FLAGS": "-O2",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "linux-gcc-ubsan-ootree-full",
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (full)",
"inherits": ["default-full-configuration", "linux-gcc-ubsan-ootree-fast"]
},
{
"name": "linux-gcc-asan-ootree-fast",
"displayName": "Linux x86_64: GCC / Asan / Out of tree (fast)",
"inherits": "linux-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Asan",
"CMAKE_C_FLAGS": "-O2",
"CMAKE_CXX_FLAGS": "-O2",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "linux-gcc-asan-ootree-full",
"displayName": "Linux x86_64: GCC / Asan / Out of tree (full)",
"inherits": ["default-full-configuration", "linux-gcc-asan-ootree-fast"]
},
{
"name": "linux-gcc-debug-ootree-skeleton-fast",
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (fast)",
"inherits": "linux-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_C_FLAGS": "-O2",
"CMAKE_CXX_FLAGS": "-O2",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "linux-gcc-debug-ootree-skeleton-full",
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (full)",
"inherits": ["default-full-configuration", "linux-gcc-debug-ootree-skeleton-fast"]
},
{
"name": "linux-gcc-debug-intree-m32-skeleton-fast",
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (fast)",
"inherits": "linux-config-base",
"binaryDir": "${sourceDir}",
"installDir": "${sourceDir}/install",
"architecture": {
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_C_FLAGS": "-O2 -m32",
"CMAKE_CXX_FLAGS": "-O2 -m32",
"CMAKE_EXE_LINKER_FLAGS": "-m32",
"CMAKE_SHARED_LINKER_FLAGS": "-m32",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "linux-gcc-debug-intree-m32-skeleton-full",
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (full)",
"inherits": ["default-full-configuration", "linux-gcc-debug-intree-m32-skeleton-fast"]
},
{
"name": "linux-gcc-release-ootree-skeleton-fast",
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (fast)",
"inherits": "linux-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "linux-gcc-release-ootree-skeleton-full",
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (full)",
"inherits": ["default-full-configuration", "linux-gcc-release-ootree-skeleton-fast"]
},
{
"name": "linux-gcc-valgrind-ootree-fast",
"displayName": "Linux x86_64: GCC / Valgrind / Out of tree (fast)",
"inherits": ["linux-gcc-release-ootree-skeleton-fast"]
},
{
"name": "linux-gcc-valgrind-ootree-full",
"displayName": "Linux x86_64: GCC / Valgrind / Out of tree (full)",
"inherits": ["linux-gcc-release-ootree-skeleton-full"]
},
{
"name": "macos-config-base",
"hidden": true,
"generator": "Unix Makefiles",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++"
}
},
{
"name": "macos-clang-debug-ootree-skeleton-fast",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (fast)",
"inherits": "macos-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_C_FLAGS": "-O2",
"CMAKE_CXX_FLAGS": "-O2",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "macos-clang-debug-ootree-skeleton-full",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (full)",
"inherits": ["default-full-configuration", "macos-clang-debug-ootree-skeleton-fast"]
},
{
"name": "macos-clang-debug-intree-skeleton-fast",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (fast)",
"inherits": "macos-config-base",
"binaryDir": "${sourceDir}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_C_FLAGS": "-O2",
"CMAKE_CXX_FLAGS": "-O2",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "macos-clang-debug-intree-skeleton-full",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (full)",
"inherits": ["default-full-configuration", "macos-clang-debug-intree-skeleton-fast"]
},
{
"name": "macos-clang-release-ootree-skeleton-fast",
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (fast)",
"inherits": "macos-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "macos-clang-release-ootree-skeleton-full",
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (full)",
"inherits": ["default-full-configuration", "macos-clang-release-ootree-skeleton-fast"]
},
{
"name": "windows-config-base",
"hidden": true,
"generator": "Visual Studio 17 2022",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_C_COMPILER": "cl",
"CMAKE_CXX_COMPILER": "cl"
}
},
{
"name": "windows-msvc-debug-ootree-fast",
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (fast)",
"inherits": "windows-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "windows-msvc-debug-ootree-full",
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (full)",
"inherits": ["default-full-configuration", "windows-msvc-debug-ootree-fast"]
},
{
"name": "windows-msvc-debug-intree-fast",
"displayName": "Windows x86_64: MSVC / Debug / In tree (fast)",
"inherits": "windows-config-base",
"binaryDir": "${sourceDir}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "windows-msvc-debug-intree-full",
"displayName": "Windows x86_64: MSVC / Debug / In tree (full)",
"inherits": ["default-full-configuration", "windows-msvc-debug-intree-fast"]
},
{
"name": "windows-msvc-release-ootree-fast",
"displayName": "Windows x86_64: MSVC / Release / Out of tree (fast)",
"inherits": "windows-config-base",
"binaryDir": "${sourceDir}/.build/${presetName}",
"installDir": "${sourceDir}/install",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"RE2C_BUILD_RE2GO": false,
"RE2C_BUILD_RE2RUST": false
}
},
{
"name": "windows-msvc-release-ootree-full",
"displayName": "Windows x86_64: MSVC / Release / Out of tree (full)",
"inherits": ["default-full-configuration", "windows-msvc-release-ootree-fast"]
}
],
"buildPresets": [
{
"name": "linux-build-base",
"hidden": true,
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
}
},
{
"name": "linux-gcc-ubsan-ootree-fast",
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (fast)",
"configurePreset": "linux-gcc-ubsan-ootree-fast",
"inherits": "linux-build-base",
"configuration": "Ubsan"
},
{
"name": "linux-gcc-ubsan-ootree-full",
"displayName": "Linux x86_64: GCC / Ubsan / Out of tree (full)",
"configurePreset": "linux-gcc-ubsan-ootree-full",
"inherits": "linux-build-base",
"configuration": "Ubsan"
},
{
"name": "linux-gcc-asan-ootree-fast",
"displayName": "Linux x86_64: GCC / Asan / Out of tree (fast)",
"configurePreset": "linux-gcc-asan-ootree-fast",
"inherits": "linux-build-base",
"configuration": "Asan"
},
{
"name": "linux-gcc-asan-ootree-full",
"displayName": "Linux x86_64: GCC / Asan / Out of tree (full)",
"configurePreset": "linux-gcc-asan-ootree-full",
"inherits": "linux-build-base",
"configuration": "Asan"
},
{
"name": "linux-gcc-debug-ootree-skeleton-fast",
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (fast)",
"configurePreset": "linux-gcc-debug-ootree-skeleton-fast",
"inherits": "linux-build-base",
"configuration": "Debug"
},
{
"name": "linux-gcc-debug-ootree-skeleton-full",
"displayName": "Linux x86_64: GCC / Debug / Skeleton / Out of tree (full)",
"configurePreset": "linux-gcc-debug-ootree-skeleton-full",
"inherits": "linux-build-base",
"configuration": "Debug"
},
{
"name": "linux-gcc-debug-intree-m32-skeleton-fast",
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (fast)",
"configurePreset": "linux-gcc-debug-intree-m32-skeleton-fast",
"inherits": "linux-build-base",
"configuration": "Debug"
},
{
"name": "linux-gcc-debug-intree-m32-skeleton-full",
"displayName": "Linux x86: GCC / Debug / Skeleton / In tree (full)",
"configurePreset": "linux-gcc-debug-intree-m32-skeleton-full",
"inherits": "linux-build-base",
"configuration": "Debug"
},
{
"name": "linux-gcc-release-ootree-skeleton-fast",
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (fast)",
"configurePreset": "linux-gcc-release-ootree-skeleton-fast",
"inherits": "linux-build-base",
"configuration": "Release"
},
{
"name": "linux-gcc-release-ootree-skeleton-full",
"displayName": "Linux x86_64: GCC / Release / Skeleton / Out of tree (full)",
"configurePreset": "linux-gcc-release-ootree-skeleton-full",
"inherits": "linux-build-base",
"configuration": "Release"
},
{
"name": "linux-gcc-valgrind-ootree-fast",
"displayName": "Linux x86_64: GCC / Valgrind / Out of tree (fast)",
"configurePreset": "linux-gcc-valgrind-ootree-fast",
"inherits": "linux-build-base",
"configuration": "Release"
},
{
"name": "linux-gcc-valgrind-ootree-full",
"displayName": "Linux x86_64: GCC / Valgrind / Out of tree (full)",
"configurePreset": "linux-gcc-valgrind-ootree-full",
"inherits": "linux-build-base",
"configuration": "Release"
},
{
"name": "macos-build-base",
"hidden": true,
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
},
{
"name": "macos-clang-debug-ootree-skeleton-fast",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (fast)",
"configurePreset": "macos-clang-debug-ootree-skeleton-fast",
"inherits": "macos-build-base",
"configuration": "Debug"
},
{
"name": "macos-clang-debug-ootree-skeleton-full",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / Out of tree (full)",
"configurePreset": "macos-clang-debug-ootree-skeleton-full",
"inherits": "macos-build-base",
"configuration": "Debug"
},
{
"name": "macos-clang-debug-intree-skeleton-fast",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (fast)",
"configurePreset": "macos-clang-debug-intree-skeleton-fast",
"inherits": "macos-build-base",
"configuration": "Debug"
},
{
"name": "macos-clang-debug-intree-skeleton-full",
"displayName": "macOS x86_64: Clang / Debug / Skeleton / In tree (full)",
"configurePreset": "macos-clang-debug-intree-skeleton-full",
"inherits": "macos-build-base",
"configuration": "Debug"
},
{
"name": "macos-clang-release-ootree-skeleton-fast",
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (fast)",
"configurePreset": "macos-clang-release-ootree-skeleton-fast",
"inherits": "macos-build-base",
"configuration": "Release"
},
{
"name": "macos-clang-release-ootree-skeleton-full",
"displayName": "macOS x86_64: CLang / Release / Skeleton / Out of tree (full)",
"configurePreset": "macos-clang-release-ootree-skeleton-full",
"inherits": "macos-build-base",
"configuration": "Release"
},
{
"name": "windows-build-base",
"hidden": true,
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "windows-msvc-debug-ootree-fast",
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (fast)",
"configurePreset": "windows-msvc-debug-ootree-fast",
"inherits": "windows-build-base",
"configuration": "Debug"
},
{
"name": "windows-msvc-debug-ootree-full",
"displayName": "Windows x86_64: MSVC / Debug / Out of tree (full)",
"configurePreset": "windows-msvc-debug-ootree-full",
"inherits": "windows-build-base",
"configuration": "Debug"
},
{
"name": "windows-msvc-debug-intree-fast",
"displayName": "Windows x86_64: MSVC / Debug / In tree (fast)",
"configurePreset": "windows-msvc-debug-intree-fast",
"inherits": "windows-build-base",
"configuration": "Debug"
},
{
"name": "windows-msvc-debug-intree-full",
"displayName": "Windows x86_64: MSVC / Debug / In tree (full)",
"configurePreset": "windows-msvc-debug-intree-full",
"inherits": "windows-build-base",
"configuration": "Debug"
},
{
"name": "windows-msvc-release-ootree-fast",
"displayName": "Windows x86_64: MSVC / Release / Out of tree (fast)",
"configurePreset": "windows-msvc-release-ootree-fast",
"inherits": "windows-build-base",
"configuration": "Release"
},
{
"name": "windows-msvc-release-ootree-full",
"displayName": "Windows x86_64: MSVC / Release / Out of tree (full)",
"configurePreset": "windows-msvc-release-ootree-full",
"inherits": "windows-build-base",
"configuration": "Release"
}
]
}
+67
View File
@@ -0,0 +1,67 @@
[re2c][re2c] was written in 1993 by Peter Bumbulis. Since then it has been
maintained and developed by multiple volunteers. Contributions are welcome,
please have a look at the guidelines below.
## Contributions
The preferred form of a contribution is a pull request on GitHub. Patches sent
by email are also fine (but less convenient). Discussion in
[GitHub issues][issues] is welcome. Email threads are also fine (but less
convenient).
## Language guidelines
re2c is written in C++ (the current standard is C++11). The algorithms and
mathematical concepts used in the code are quite complex, so the code itself
should stay simple and let the developer focus on the underlying logic, without
the language getting in the way. For example, try to avoid complex object
hierarchies and excessive use of template metaprogramming.
The line length limit is 100 characters, indentation is 4 spaces, and the
indentation style is egyptian (the opening brace is on the same line). This is
the approximate `astyle` command to auto-format re2c source code (it requires
manual tweaking for argument/initializer lists and multiline comments):
$ # run in source directory
$ astyle --style=google \
--max-code-length=100 \
--align-pointer=type \
--align-reference=type \
--keep-one-line-statements \
--suffix=none \
--recursive '*'
## Regenerating bootstrap files
By default re2c uses bootstrap files for autogenerated sources (lexers, parsers,
docs) and does not attempt to regenerate them. Developers may need to enable
"regeneration mode" if they modify the corresponding source files.
For changes that affect lexers (`.re` files), regeneration mode is configured
with options `--enable-lexers` (Autotools) or `-DRE2C_REBUILD_LEXERS=ON`
(CMake). `RE2C_FOR_BUILD` should be defined as a path to an existing re2c
executable that will be used to regenerate the lexers.
For changes that affect parsers (`.ypp` files), regeneration mode is configured
with options `--enable-parsers` (Autotools) or `-DRE2C_REBUILD_PARSERS=ON`
(CMake). In this case `bison` must be installed on the system. Otherwise
Autoconf or CMake will fail at configuration stage.
For changes that update documentation, it is necessary to rebuild the bootstrap
manpages by reconfiguring and rebuilding re2c with options `--enable-docs`
(Autotools) or `-DRE2C_REBUILD_DOCS=ON` (CMake).
Please do not commit trivial updates to the bootstrap files, such as changes of
the generator version or generation date.
## Commit messages
The headline should use present tense and start with a capital letter. Commit
messages should be as descriptive as possible and avoid uncertain terms like
"fix", "refactoring", "code cleanup" and so on. Long commit messages with
explanations, examples and test instructions are welcome.
Unrelated changes should be split into multiple commits.
[re2c]: http://re2c.org/
[issues]: https://github.com/skvadrik/re2c/issues
+46
View File
@@ -0,0 +1,46 @@
If you run out of ideas of how to make re2c better...
## Multibyte switch
Reading multiple characters at a time is problematic due to the absence of
alignment guarantees: even if unaligned reads are supported by the CPU, they are
still likely to be slow.
But it should be possible to read a few characters, combine them into one using
shifts and bitwise operations, and then switch on the combined character. It can
be done with existing API; no new primitives are needed.
Of course it will only help in cases when the underlying DFA has long "chains"
of transitions without branches that can be collapsed into one transition. But
the optimization can be local (applied to some parts of the DFA).
## User-defined language support
The idea originated in a linux.org.ru thread (in Russian):
https://www.linux.org.ru/news/development/16759268?cid=16762746
The original idea was to provide an API to render the generated AST into code
and let the user implement it in the form of a plugin/library. This is
problematic because 1) there is no stable AST, and 2) there are some language-
agnostic optimizations and decisions that re2c takes way before the final
rendering phase (so it is not as simple as providing a bunch or functions to
generate code for different AST nodes).
There may be another way to provide any-language support: let the user define a
set of primitives/configurations that re2c will use for language-agnostic
decisions and for code generation (some of them exist already, but not enough to
fully redefine the target language). This is akin to the idea of Midnight
Commander's skins or syntax files. re2c can provide default syntax files for
some languages (it already provides "standard" Unicode categories).
## Negation and complement
It would be good to support these operations on regular expressions, but it
requires some research. Does TDFA present any special difficulties?
## Location support
It would be good to have something like Bison locations (automatic tracking of
line/column/filename inforamtion). This is primarily useful for tokenizers and
large lexers.
+13
View File
@@ -0,0 +1,13 @@
re2c is distributed with no warranty whatever. The code is certain to contain
errors. Neither authors nor contributors take any responsibility for the
consequences of its use.
re2c is in the public domain. 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.
+41
View File
@@ -0,0 +1,41 @@
If re2c is unmaintained for a long time and starts to bitrot, or if you have a
fork and need to make it as simple as possible, here is a list of things that
can be cut off rather safely vs. things that are essential.
## Things to remove
These are mostly experimental research projects that have never been used
outside of lab (to the best of author's knowledge, that is):
- Benchmarks: drop optional dependencies on re2, google-benchmark, Java (libre2c
has JNI bindings); simplify the build system(s).
- libre2c: drop static/dynamic libraries support in the build system(s), e.g.
Libtool; remove a few internal options and a bunch of explicit template
instantiations in TDFA construction code that exist only for libre2c.
- One of the build systems: Autotools or CMake, whichever you like less. Someone
will get unhappy in both cases (Windows is supported only by CMake, but distro
maintainers may have decades old recipes based on Autotools).
## Things to remove only as a last resort
- Skeleton: it is really useful for testing and codegen validation, but re2c can
live without it (and a few large tests can be dropped).
- Fuzzers: same here, they are really useful to find bugs and test hypotheses,
but re2c can function without them.
## Things to keep
- Existing configurations / options / syntax: re2c must stay backwards
compatible or it will become unusable. One exception is internal/debug options
which may be removed with caution. For the rest, keep them as deprecated even
if they do nothing.
- Language backends: they add little code complexity for a lot of value (and
discipline in the codegen subsystem).
- Documentation (both on `master` branch and the website on `gh-pages` and
`gh-pages-gen` branches). Without docs no one will know how to use re2c.
+506
View File
@@ -0,0 +1,506 @@
SUBDIRS = .
# stdlib directory
stdlibdir = $(datadir)/re2c/stdlib
# do not add compiler options/warnings here, add them in configure.ac
AM_CXXFLAGS = $(CXXFLAGSDEFAULT)
AM_CXXFLAGS += -DRE2C_STDLIB_DIR='"$(stdlibdir)/"'
if DEBUG
AM_CXXFLAGS += -DRE2C_DEBUG
endif
RE2CFLAGS = -b -W -Wno-match-empty-string --no-generation-date
# binary
bin_PROGRAMS = re2c
noinst_PROGRAMS =
# sources
re2c_HDR = \
src/constants.h \
src/codegen/code.h \
src/codegen/output.h \
src/codegen/helpers.h \
src/options/opt.h \
src/options/symtab.h \
src/adfa/adfa.h \
src/cfg/cfg.h \
src/dfa/closure_leftmost.h \
src/dfa/closure_posix.h \
src/dfa/determinization.h \
src/dfa/dfa.h \
src/dfa/posix_precedence.h \
src/dfa/tag_history.h \
src/dfa/tagver_table.h \
src/dfa/tcmd.h \
src/nfa/nfa.h \
src/encoding/ebcdic.h \
src/encoding/enc.h \
src/encoding/range_suffix.h \
src/encoding/utf8.h \
src/encoding/utf16.h \
src/msg/location.h \
src/msg/msg.h \
src/msg/ver_to_vernum.h \
src/msg/warn.h \
src/regexp/regexp.h \
src/regexp/rule.h \
src/regexp/tag.h \
src/skeleton/mtag_trie.h \
src/skeleton/path.h \
src/skeleton/skeleton.h \
src/parse/ast.h \
src/parse/input.h \
src/debug/debug.h \
src/util/allocator.h \
src/util/attribute.h \
src/util/containers.h \
src/util/check.h \
src/util/file_utils.h \
src/util/forbid_copy.h \
src/util/hash32.h \
src/util/nowarn_in_bison.h \
src/util/range.h \
src/util/string_utils.h \
src/util/u32lim.h
re2c_SRC = \
src/codegen/helpers.cc \
src/codegen/output.cc \
src/codegen/pass1_analyze.cc \
src/codegen/pass2_generate.cc \
src/codegen/pass3_fixup.cc \
src/codegen/pass4_render.cc \
src/options/opt.cc \
src/options/symtab.cc \
src/nfa/re_to_nfa.cc \
src/adfa/adfa.cc \
src/debug/dump_adfa.cc \
src/debug/dump_cfg.cc \
src/debug/dump_dfa.cc \
src/debug/dump_dfa_tree.cc \
src/debug/dump_interf.cc \
src/debug/dump_nfa.cc \
src/cfg/cfg.cc \
src/cfg/compact.cc \
src/cfg/dce.cc \
src/cfg/freeze.cc \
src/cfg/interfere.cc \
src/cfg/liveanal.cc \
src/cfg/normalize.cc \
src/cfg/optimize.cc \
src/cfg/rename.cc \
src/cfg/varalloc.cc \
src/dfa/closure.cc \
src/dfa/dead_rules.cc \
src/dfa/determinization.cc \
src/dfa/fallback_tags.cc \
src/dfa/fillpoints.cc \
src/dfa/find_state.cc \
src/dfa/minimization.cc \
src/dfa/tagver_table.cc \
src/dfa/tcmd.cc \
src/encoding/ebcdic.cc \
src/encoding/enc.cc \
src/encoding/range_suffix.cc \
src/encoding/utf8.cc \
src/encoding/utf16.cc \
src/msg/msg.cc \
src/msg/warn.cc \
src/regexp/ast_to_re.cc \
src/regexp/default_tags.cc \
src/regexp/fixed_tags.cc \
src/regexp/nullable.cc \
src/regexp/regexp.cc \
src/regexp/split_charset.cc \
src/skeleton/control_flow.cc \
src/skeleton/generate_code.cc \
src/skeleton/generate_data.cc \
src/skeleton/maxpath.cc \
src/skeleton/skeleton.cc \
src/parse/ast.cc \
src/parse/input.cc \
src/util/file_utils.cc \
src/util/string_utils.cc \
src/util/range.cc
re2c_SOURCES = \
src/main.cc \
$(re2c_HDR) \
$(re2c_SRC)
# autogenerated sources
re2c_GEN_HELP = src/msg/help.cc
re2c_GEN_LEX = src/parse/lex.cc
re2c_GEN_PARSER = src/parse/parser.cc
re2c_GEN_PARSER_HDR = src/parse/parser.h
re2c_GEN_VER_TO_VERNUM = src/msg/ver_to_vernum.cc
re2c_GEN_SRC = \
$(re2c_GEN_HELP) \
$(re2c_GEN_LEX) \
$(re2c_GEN_PARSER) \
$(re2c_GEN_VER_TO_VERNUM) \
src/parse/lex_conf.cc \
src/options/parse_opts.cc
re2c_GEN_HDR = \
src/parse/lex.h \
$(re2c_GEN_PARSER_HDR)
re2c_GEN = \
$(re2c_GEN_SRC) \
$(re2c_GEN_HDR)
nodist_re2c_SOURCES = $(re2c_GEN)
# custom rules create headers and must go before normal rules
BUILT_SOURCES = $(re2c_GEN_SRC)
# bootstrap sources
re2c_BOOT_PARSER = bootstrap/src/parse/parser.cc
re2c_BOOT_PARSER_HDR = bootstrap/src/parse/parser.h
re2c_BOOT_DOC_C = bootstrap/doc/re2c.1
re2c_BOOT_DOC_GO = bootstrap/doc/re2go.1
re2c_BOOT_DOC_RUST = bootstrap/doc/re2rust.1
re2c_BOOT_HELP = bootstrap/src/msg/help.cc
re2c_BOOT = \
$(re2c_BOOT_DOC_C) \
$(re2c_BOOT_DOC_GO) \
$(re2c_BOOT_DOC_RUST) \
$(re2c_BOOT_HELP) \
$(re2c_BOOT_PARSER) \
$(re2c_BOOT_PARSER_HDR) \
bootstrap/src/parse/lex.cc \
bootstrap/src/parse/lex.h \
bootstrap/src/parse/lex_conf.cc \
bootstrap/src/options/parse_opts.cc \
bootstrap/src/msg/ver_to_vernum.cc
# custom sources
re2c_CUSTOM_PARSER = src/parse/parser.ypp
re2c_CUSTOM_HELP = doc/help.rst
re2c_CUSTOM = \
$(re2c_CUSTOM_PARSER) \
$(re2c_CUSTOM_HELP) \
src/parse/lex.re \
src/parse/lex_conf.re \
src/options/parse_opts.re \
src/msg/ver_to_vernum.re
# docs
re2c_SRC_DOC = doc/manpage.rst
re2c_SRC_DOC_EXT = \
doc/manual/api/interface.rst_ \
doc/manual/conditions/blocks.rst_ \
doc/manual/conditions/conditions.rst_ \
doc/manual/configurations/configurations.rst_ \
doc/manual/directives/directives.rst_ \
doc/manual/dot/dot.rst_ \
doc/manual/encodings/encodings.rst_ \
doc/manual/eof/01_sentinel.rst_ \
doc/manual/eof/02_bounds_checking.rst_ \
doc/manual/eof/03_eof_rule.rst_ \
doc/manual/eof/04_generic_api.rst_ \
doc/manual/eof/eof.rst_ \
doc/manual/fill/01_fill.rst_ \
doc/manual/fill/02_fill.rst_ \
doc/manual/fill/fill.rst_ \
doc/manual/headers/headers.rst_ \
doc/manual/includes/includes.rst_ \
doc/manual/options/debug.rst_ \
doc/manual/options/internal.rst_ \
doc/manual/options/options.rst_ \
doc/manual/regexps/regular_expressions.rst_ \
doc/manual/reuse/reuse.rst_ \
doc/manual/skeleton/skeleton.rst_ \
doc/manual/state/state.rst_ \
doc/manual/submatch/submatch_example_mtags.rst_ \
doc/manual/submatch/submatch_example_posix.rst_ \
doc/manual/submatch/submatch_example_stags_fill.rst_ \
doc/manual/submatch/submatch_example_stags.rst_ \
doc/manual/submatch/submatch.rst_ \
doc/manual/synopsis.rst_ \
doc/manual/syntax/api1.rst_ \
doc/manual/syntax/api2_c.rst_ \
doc/manual/syntax/api2_go.rst_ \
doc/manual/syntax/api2_rust.rst_ \
doc/manual/syntax/api3.rst_ \
doc/manual/syntax/intro.rst_ \
doc/manual/syntax/syntax.rst_ \
doc/manual/warnings/warnings_general.rst_ \
doc/manual/warnings/warnings_list.rst_ \
examples/c/01_basic.re \
examples/c/01_basic.c \
examples/c/conditions/parse_u32_blocks.re \
examples/c/conditions/parse_u32_conditions.re \
examples/c/encodings/unicode_identifier.re \
examples/c/eof/01_sentinel.re \
examples/c/eof/02_bounds_checking.re \
examples/c/eof/03_eof_rule.re \
examples/c/eof/05_generic_api_eof_rule.re \
examples/c/fill/01_fill.re \
examples/c/fill/02_fill.re \
examples/c/headers/header.re \
examples/c/headers/lexer/state.h \
examples/c/includes/include.re \
examples/c/includes/definitions.h \
examples/c/reuse/reuse.re \
examples/c/reuse/usedir.re \
examples/c/state/push.re \
examples/c/submatch/01_stags_fill.re \
examples/c/submatch/01_stags.re \
examples/c/submatch/02_mtags.re \
examples/c/submatch/03_posix.re \
examples/go/01_basic.re \
examples/go/01_basic.go \
examples/go/conditions/parse_u32_blocks.re \
examples/go/conditions/parse_u32_conditions.re \
examples/go/encodings/unicode_identifier.re \
examples/go/eof/01_sentinel.re \
examples/go/eof/02_bounds_checking.re \
examples/go/eof/03_eof_rule.re \
examples/go/eof/05_generic_api_eof_rule.re \
examples/go/fill/01_fill.re \
examples/go/fill/02_fill.re \
examples/go/headers/header.re \
examples/go/headers/lexer/state.go \
examples/go/includes/include.re \
examples/go/includes/definitions.go \
examples/go/reuse/reuse.re \
examples/go/reuse/usedir.re \
examples/go/state/push.re \
examples/go/submatch/01_stags_fill.re \
examples/go/submatch/01_stags.re \
examples/go/submatch/02_mtags.re \
examples/go/submatch/03_posix.re \
examples/rust/01_basic.re \
examples/rust/01_basic.rs \
examples/rust/conditions/parse_u32_blocks.re \
examples/rust/conditions/parse_u32_conditions.re \
examples/rust/encodings/unicode_identifier.re \
examples/rust/eof/01_sentinel.re \
examples/rust/eof/02_bounds_checking.re \
examples/rust/eof/03_eof_rule.re \
examples/rust/eof/05_generic_api_eof_rule.re \
examples/rust/fill/01_fill.re \
examples/rust/fill/02_fill.re \
examples/rust/headers/header.re \
examples/rust/headers/lexer/state.rs \
examples/rust/includes/include.re \
examples/rust/includes/definitions.rs \
examples/rust/reuse/reuse.re \
examples/rust/reuse/usedir.re \
examples/rust/state/push.re \
examples/rust/submatch/01_stags_fill.re \
examples/rust/submatch/01_stags.re \
examples/rust/submatch/02_mtags.re \
examples/rust/submatch/03_posix.re
DOC_C = doc/re2c.1
DOCS = $(DOC_C)
if WITH_GOLANG
DOC_GO = doc/re2go.1
DOCS += $(DOC_GO)
endif
if WITH_RUST
DOC_RUST = doc/re2rust.1
DOCS += $(DOC_RUST)
endif
man_MANS = $(DOCS)
# include files (stdlib)
dist_stdlib_DATA = include/unicode_categories.re
BAZELFILES := \
BUILD.bazel \
WORKSPACE \
bazel
CMAKEFILES := \
CMakeLists.txt \
CMakePresets.json \
cmake
EXTRA_DIST = \
$(re2c_BOOT) \
$(re2c_CUSTOM) \
$(re2c_SRC_DOC_EXT) \
$(BAZELFILES) \
$(CMAKEFILES) \
BUILD.md \
CHANGELOG \
CONTRIBUTING.md \
IDEAS.md \
LICENSE \
MAINTAINERS.md \
NO_WARRANTY \
README.md \
autogen.sh \
build \
examples \
test
CLEANFILES = \
$(re2c_GEN) \
$(DOCS)
if REBUILD_LEXERS
# generate lexer and update bootstrap files
.re.cc:
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(RE2C_FOR_BUILD) $(RE2CFLAGS) -o $@ $<
$(AM_V_GEN)cp $(@:cc=[ch]*) $(top_srcdir)/bootstrap/$(@D);
else
# copy bootstrap files
.re.cc:
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)cp $(top_srcdir)/bootstrap/$(@:cc=*) $(@D)
$(AM_V_at)echo "Reconfigure with --enable-lexers to regenerate $@"
endif
if REBUILD_PARSERS
# generate lexer and update bootstrap files
.ypp.cc:
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(BISON) --warnings --output=$@ --defines=$(@:cc=h) $<
$(AM_V_GEN)cp $@ $(@:cc=h) $(top_srcdir)/bootstrap/$(@D);
else
# copy bootstrap files
.ypp.cc:
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)cp $(top_srcdir)/bootstrap/$(@:cc=*) $(@D);
$(AM_V_at)echo "Reconfigure with --enable-parsers to regenerate $@"
endif
# lexer depends on bison-generated header
$(re2c_GEN_LEX): $(re2c_GEN_PARSER)
# rebuild all re2c sources using newly built re2c
.PHONY: bootstrap
bootstrap: all
rm $(re2c_GEN)
$(MAKE) all
.PHONY: docs
if REBUILD_DOCS
docs: $(DOCS) $(re2c_GEN_HELP)
RST2TXT = $(top_srcdir)/build/rst2txt.py
RST2MAN = $(top_srcdir)/build/rst2man.py
SPLITMAN = $(top_srcdir)/build/split_man.py
# generate manpage for C
$(DOC_C): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN) $(RST2MAN)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(PYTHON) $(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).c c \
&& $(PYTHON) $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).c > $@ \
&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_C) \
&& rm $(top_builddir)/$(re2c_SRC_DOC).c
# generate manpage for Go
$(DOC_GO): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN) $(RST2MAN)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(PYTHON) $(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).go go \
&& $(PYTHON) $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).go > $@ \
&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_GO) \
&& rm $(top_builddir)/$(re2c_SRC_DOC).go
# generate manpage for Rust
$(DOC_RUST): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN) $(RST2MAN)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(PYTHON) $(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).rust rust \
&& $(PYTHON) $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).rust > $@ \
&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_RUST) \
&& rm $(top_builddir)/$(re2c_SRC_DOC).rust
# generate help
$(re2c_GEN_HELP): $(re2c_CUSTOM_HELP) $(re2c_SRC_DOC_EXT) $(RST2TXT)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(PYTHON) $(RST2TXT) --variable-name=help $(top_builddir)/$(re2c_CUSTOM_HELP) $@ \
&& cp $@ $(top_srcdir)/$(re2c_BOOT_HELP)
else
docs: $(DOCS) $(re2c_GEN_HELP)
$(AM_V_at)echo "Reconfigure with --enable-docs to rebuild docs"
# copy bootstrap manpage for C
$(DOC_C): $(re2c_BOOT_DOC_C)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_C) $@
# copy bootstrap manpage for Go
$(DOC_GO): $(re2c_BOOT_DOC_GO)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_GO) $@
# copy bootstrap manpage for Rust
$(DOC_RUST): $(re2c_BOOT_DOC_RUST)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_RUST) $@
# copy bootstrap help
$(re2c_GEN_HELP): $(re2c_BOOT_HELP)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_HELP) $@
endif
all-local: docs $(re2c_BOOT_PARSER)
# tests
re2c_TESTSUITE = run_tests.py
.PHONY: tests
tests: all $(re2c_TESTSUITE)
$(PYTHON) $(top_builddir)/$(re2c_TESTSUITE)
.PHONY: vtests
vtests: all $(re2c_TESTSUITE)
$(PYTHON) $(top_builddir)/$(re2c_TESTSUITE) --valgrind
.PHONY: wtests
wtests: all $(re2c_TESTSUITE)
$(PYTHON) $(top_builddir)/$(re2c_TESTSUITE) --wine -j1
re2c_test_range_SOURCES = \
src/test/range/test-impl.h \
src/test/range/test.cc \
src/test/range/test.h \
src/util/range.cc \
src/util/range.h
re2c_test_s_to_n32_unsafe_SOURCES = \
src/test/s_to_n32_unsafe/test.cc \
src/util/string_utils.cc
re2c_test_ver_to_vernum_SOURCES = \
src/test/ver_to_vernum/test.cc \
$(re2c_GEN_VER_TO_VERNUM)
re2c_test_argsubst_SOURCES = \
src/test/argsubst/test.cc
check_PROGRAMS = \
re2c_test_range \
re2c_test_s_to_n32_unsafe \
re2c_test_ver_to_vernum \
re2c_test_argsubst
TESTS = \
$(re2c_TESTSUITE) \
$(check_PROGRAMS)
# benchmarks
if WITH_BENCHMARKS
SUBDIRS += benchmarks/submatch_dfa_aot
EXTRA_DIST += benchmarks/submatch_dfa_aot
endif
# libre2c
if WITH_LIBS
ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES =
include $(top_srcdir)/Makefile.lib.am
endif
# re2go
if WITH_GOLANG
bin_PROGRAMS += re2go
re2go_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=Lang::GO
re2go_SOURCES = $(re2c_SOURCES)
nodist_re2go_SOURCES = $(nodist_re2c_SOURCES)
endif
# re2rust
if WITH_RUST
bin_PROGRAMS += re2rust
re2rust_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=Lang::RUST
re2rust_SOURCES = $(re2c_SOURCES)
nodist_re2rust_SOURCES = $(nodist_re2c_SOURCES)
endif
+180
View File
@@ -0,0 +1,180 @@
# this file is incomplete and should be included from the main Makefile.am
lib_LTLIBRARIES += libre2c.la
libre2c_la_CXXFLAGS = $(AM_CXXFLAGS)
libre2c_la_LDFLAGS = -module -no-undefined
libre2c_la_HDR = \
lib/lex.h \
lib/regcomp_dfa_multipass.h \
lib/regex.h \
lib/regex_impl.h \
lib/regoff_trie.h \
src/constants.h \
src/codegen/code.h \
src/options/opt.h \
src/options/symtab.h \
src/adfa/adfa.h \
src/cfg/cfg.h \
src/dfa/closure_leftmost.h \
src/dfa/closure_posix.h \
src/dfa/determinization.h \
src/dfa/dfa.h \
src/dfa/posix_precedence.h \
src/dfa/tag_history.h \
src/dfa/tagver_table.h \
src/dfa/tcmd.h \
src/nfa/nfa.h \
src/encoding/ebcdic.h \
src/encoding/enc.h \
src/encoding/range_suffix.h \
src/encoding/utf8.h \
src/encoding/utf16.h \
src/msg/location.h \
src/msg/msg.h \
src/msg/ver_to_vernum.h \
src/msg/warn.h \
src/regexp/regexp.h \
src/regexp/rule.h \
src/regexp/tag.h \
src/skeleton/path.h \
src/skeleton/skeleton.h \
src/parse/ast.h \
src/parse/input.h \
src/parse/parser.h \
src/debug/debug.h \
src/util/allocator.h \
src/util/attribute.h \
src/util/check.h \
src/util/containers.h \
src/util/file_utils.h \
src/util/forbid_copy.h \
src/util/hash32.h \
src/util/nowarn_in_bison.h \
src/util/range.h \
src/util/string_utils.h \
src/util/u32lim.h
libre2c_la_SRC = \
lib/regcomp.cc \
lib/regexec.cc \
lib/regexec_dfa.cc \
lib/regexec_dfa_multipass.cc \
lib/regexec_nfa_leftmost.cc \
lib/regexec_nfa_leftmost_trie.cc \
lib/regexec_nfa_posix.cc \
lib/regexec_nfa_posix_trie.cc \
lib/regfree.cc \
lib/stubs.cc \
src/parse/ast.cc \
src/parse/input.cc \
src/options/opt.cc \
src/options/symtab.cc \
src/cfg/cfg.cc \
src/cfg/compact.cc \
src/cfg/dce.cc \
src/cfg/freeze.cc \
src/cfg/interfere.cc \
src/cfg/liveanal.cc \
src/cfg/normalize.cc \
src/cfg/optimize.cc \
src/cfg/rename.cc \
src/cfg/varalloc.cc \
src/dfa/closure.cc \
src/debug/dump_adfa.cc \
src/debug/dump_cfg.cc \
src/debug/dump_dfa.cc \
src/debug/dump_dfa_tree.cc \
src/debug/dump_interf.cc \
src/debug/dump_nfa.cc \
src/dfa/dead_rules.cc \
src/dfa/determinization.cc \
src/dfa/fallback_tags.cc \
src/dfa/fillpoints.cc \
src/dfa/find_state.cc \
src/dfa/minimization.cc \
src/dfa/tagver_table.cc \
src/dfa/tcmd.cc \
src/nfa/re_to_nfa.cc \
src/encoding/enc.cc \
src/encoding/range_suffix.cc \
src/encoding/ebcdic.cc \
src/encoding/utf16.cc \
src/encoding/utf8.cc \
src/msg/msg.cc \
src/msg/warn.cc \
src/regexp/ast_to_re.cc \
src/regexp/default_tags.cc \
src/regexp/fixed_tags.cc \
src/regexp/nullable.cc \
src/regexp/regexp.cc \
src/regexp/split_charset.cc \
src/skeleton/control_flow.cc \
src/skeleton/maxpath.cc \
src/skeleton/skeleton.cc \
src/util/range.cc \
src/util/file_utils.cc \
src/util/string_utils.cc
libre2c_la_SOURCES = \
$(libre2c_la_HDR) \
$(libre2c_la_SRC)
libre2c_la_CUSTOM = \
lib/lex.re \
lib/parse.ypp \
lib/test_helper.re \
src/msg/ver_to_vernum.re
libre2c_la_GEN_SRC = \
lib/lex.cc \
lib/parse.cc \
lib/test_helper.cc \
src/msg/ver_to_vernum.cc
libre2c_la_GEN_HDR = \
lib/parse.h
libre2c_la_GEN = \
$(libre2c_la_GEN_SRC) \
$(libre2c_la_GEN_HDR)
# custom rules create headers and must go before normal rules
BUILT_SOURCES += $(libre2c_la_GEN_SRC)
libre2c_la_BOOTSTRAP = \
bootstrap/lib/parse.cc \
bootstrap/lib/parse.h \
bootstrap/lib/lex.cc \
bootstrap/lib/test_helper.cc \
bootstrap/src/msg/ver_to_vernum.cc
nodist_libre2c_la_SOURCES = $(libre2c_la_GEN)
EXTRA_DIST += \
$(libre2c_la_BOOTSTRAP) \
$(libre2c_la_CUSTOM)
CLEANFILES += $(libre2c_la_GEN)
# lexer depends on bison-generated header
lib/lex.cc: lib/parse.cc
# tests
test_libre2c_SOURCES = \
lib/test.cc \
lib/test_helper.h \
lib/test_helper.cc
test_libre2c_LDADD = libre2c.la
check_PROGRAMS += test_libre2c
# benchmarks
if WITH_BENCHMARKS
SUBDIRS += benchmarks/submatch_nfa
SUBDIRS += benchmarks/submatch_dfa_jit
EXTRA_DIST += benchmarks/submatch_nfa
EXTRA_DIST += benchmarks/submatch_dfa_jit
if WITH_JAVA
SUBDIRS += benchmarks/submatch_java
EXTRA_DIST += benchmarks/submatch_java
endif # WITH_JAVA
endif # WITH_BENCHMARKS
+2
View File
@@ -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.
+79
View File
@@ -0,0 +1,79 @@
DESCRIPTION
-----------
re2c is a free and open-source lexer generator for C/C++, Go and Rust.
Its main goal is generating fast lexers: at least as fast as their reasonably
optimized hand-coded counterparts. Instead of using traditional table-driven
approach, re2c encodes the generated finite state automata directly in the form
of conditional jumps and comparisons. The resulting programs are faster and
often smaller than their table-driven analogues, and they are much easier to
debug and understand. re2c applies quite a few optimizations in order to speed
up and compress the generated code.
Another distinctive feature is its flexible interface: instead of assuming a
fixed program template, re2c lets the programmer write most of the interface
code and adapt the generated lexer to any particular environment.
DOCUMENTATION
-------------
Official re2c website is [re2c.org](http://re2c.org). It has a lot of examples.
DOWNLOAD
--------
Release tarballs: https://github.com/skvadrik/re2c/releases
Source code:
```
$ git clone https://github.com/skvadrik/re2c.git
$ git clone https://git.code.sf.net/p/re2c/code-git
```
Github is the main repo, sourceforge is a mirror and can be slightly outdated.
CONTRIBUTING
------------
re2c is an Open Source, community-driven project. See
[CONTRIBUTING.md](https://github.com/skvadrik/re2c/blob/master/CONTRIBUTING.md)
for details about contributions to this repository.
BUILD
-----
See BUILD.md or the [online docs](https://re2c.org/build/build.html) for
instructions how to build re2c.
FEEDBACK
--------
Bugtracker:
- https://github.com/skvadrik/re2c/issues
Mailing lists:
- re2c-general@lists.sourceforge.net
- re2c-devel@lists.sourceforge.net
IRC channels:
- irc.oftc.net/#re2c
- irc.libera.chat/#re2c
You are welcome to ask for help or share your thoughts and ideas.
AUTHORS
-------
re2c was originally written by Peter Bumbulis <peter@csg.uwaterloo.ca>. Since
then many volunteers have contributed to the project. The current maintainer is
Ulya Trofimovich <skvadrik@gmail.com>.
+14
View File
@@ -0,0 +1,14 @@
workspace(name = "re2c")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "bazel_skylib",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
],
sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
Executable → Regular
+12 -12
View File
@@ -1,16 +1,16 @@
1. Upload new and delete old documentation
1. Test windows build using mingw:
$ re2c/autogen.sh
$ re2c/build_mingw.sh
$ cd re2c/.build_mingw
$ make wtests
$ cd ../..
2. Test windows build using cygwin
2. Edit the following files:
CHANGELOG
3. Edit the following files:
- CHANGELOG
- htdocs/index.html
3. Run release script:
$ ./release.sh <version>
4. Run script release.sh:
./release.sh <version>
4. Update version to .dev
5. Write NEWS file
6. Add release notes on freshmeat
7. Don't forget to set version to .dev
5. Attach tarball (built with release.sh) to autogenerated release on github
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -i -W all
+13
View File
@@ -0,0 +1,13 @@
package(default_visibility = ["//visibility:private"])
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
exports_files([
"re2c_config.h",
])
bzl_library(
name = "re2c_bzl",
srcs = ["re2c.bzl"],
visibility = ["//visibility:public"],
)
+70
View File
@@ -0,0 +1,70 @@
# re2c generator rules - assuming that re2c is available as '@re2c//:re2c'.
load("@bazel_skylib//lib:paths.bzl", "paths")
visibility("public")
# Define supported extensions as defined by:
# . https://bazel.build/reference/be/c-cpp#cc_library_args
# . https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/rules/cpp/CppFileTypes.java
_C_SRC_EXT = [".c", ".cc", ".cpp", ".cxx", ".c++", ".C", ".cu", ".cl"]
_C_HDR_EXT = [".h", ".hh", ".hpp", ".ipp", ".hxx", ".h++", ".inc", ".inl", ".tlh", ".tli", ".H", ".tcc"]
_RE2C_EXT = [".re", ".re2c"]
def _re2c_impl(ctx):
srcs = ctx.files.srcs
if len(srcs) != 1:
fail("Attribute `srcs` must contain exactly 1 re2c source file ({exts}).".format(exts=", ".join(_RE2C_EXT)))
outs = ctx.outputs.outs
if not outs or [o for o in outs if paths.split_extension(o.path)[1] not in _C_SRC_EXT + _C_HDR_EXT]:
fail("Attribute `outs` must contain at least 1 C/C++ shource or header file ({exts}).".format(exts=", ".join(_C_SRC_EXT + _C_HDR_EXT)))
ctx.actions.run_shell(
outputs = outs + [err_file],
tools = [ctx.executable._re2c_tool],
inputs = ctx.files.srcs + ctx.files.data,
command = """
"{re2c}" "{src}" -o "{out}" {re2c_args} {includes}
""".format(
re2c = ctx.executable._re2c_tool.path,
src = srcs[0].path,
out = outs[0].path,
includes = " ".join(list(dict([("-I" + f.dirname, 1) for f in ctx.files.data]))),
re2c_args = " ".join(ctx.attr.re2c_args),
),
mnemonic = "RE2C",
progress_message = "Generating re2c %{label}",
)
_re2c_attr = {
"srcs": attr.label_list(
doc = "The re2c source.",
allow_files = _RE2C_EXT,
mandatory = True,
),
"data": attr.label_list(
doc = "Other input data files (e.g. include files).",
allow_files = _C_SRC_EXT + _C_HDR_EXT,
mandatory = False,
),
"outs": attr.output_list(
doc = "The generated output source.",
mandatory = True,
),
"re2c_args": attr.string_list(
doc = "Arguments to re2c invocation.",
),
"_re2c_tool": attr.label(
doc = "The target of the 're2c' executable.",
default = Label("//:re2c"),
allow_single_file = True,
executable = True,
cfg = "exec",
),
}
re2c_gen = rule(
attrs = _re2c_attr,
doc = """Use re2c tool to create an output file (e.g. '.cc') from a '.re' input.""",
output_to_genfiles = True,
implementation = _re2c_impl,
)
+4
View File
@@ -0,0 +1,4 @@
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_FCNTL_H 1
#define HAVE_UNISTD_H 1
+146
View File
@@ -0,0 +1,146 @@
#include <string.h>
#include "benchmarks/common/common.h"
#include "lib/regex.h"
#ifdef HAVE_RE2_RE2_H
#include "re2/re2.h"
#endif
static void add_counters(benchmark::State &state, const alg_t &,
const bench_t &bench, int captures)
{
size_t bytes = 0;
for (const char **s = bench.strings; *s; ++s) {
bytes += strlen(*s);
}
state.counters["captures"] = double(captures);
state.counters["regsize"] = double(strlen(bench.regexp));
}
void bench_regcomp_re2c(benchmark::State& state, const alg_t &alg, const bench_t &bench)
{
int err = 0;
size_t nmatch = 0;
for (auto _ : state) {
regex_t re;
err = regcomp(&re, bench.regexp, alg.flags);
nmatch = re.re_nsub;
regfree(&re);
}
if (err) {
state.SkipWithError("regcomp failed");
}
add_counters(state, alg, bench, int(nmatch) - 1);
}
void bench_regexec_re2c(benchmark::State& state, const alg_t &alg, const bench_t &bench)
{
regex_t re;
int err = regcomp(&re, bench.regexp, alg.flags);
if (err) {
state.SkipWithError("regcomp failed");
}
const bool with_hist = alg.flags & REG_SUBHIST;
const size_t nmatch = re.re_nsub;
regmatch_t *pmatch = with_hist ? NULL : new regmatch_t[nmatch];
// Do not move condition inside of the loop to avoid overhead.
if (with_hist) {
for (auto _ : state) {
for (const char **strings = bench.strings; *strings; ++strings) {
subhistory_t *h = regparse(&re, *strings, nmatch);
err |= h ? 0 : 1;
regfreesub(h);
}
}
} else {
for (auto _ : state) {
for (const char **strings = bench.strings; *strings; ++strings) {
err |= regexec(&re, *strings, nmatch, pmatch, 0);
}
}
}
if (err) {
state.SkipWithError("regexec failed");
}
add_counters(state, alg, bench, int(nmatch) - 1);
delete[] pmatch;
regfree(&re);
}
#ifdef HAVE_RE2_RE2_H
void bench_regcomp_re2(benchmark::State &state, const alg_t &alg, const bench_t &bench)
{
bool ok = true;
int argc = 0;
for (auto _ : state) {
RE2 re(bench.regexp, RE2::POSIX);
ok = re.ok();
argc = re.NumberOfCapturingGroups();
}
if (!ok) {
state.SkipWithError("regcomp failed");
}
add_counters(state, alg, bench, argc);
}
void bench_regexec_re2(benchmark::State &state, const alg_t &alg, const bench_t &bench)
{
RE2 re(bench.regexp, RE2::POSIX);
if (!re.ok()) {
state.SkipWithError("regcomp failed");
}
const int argc = re.NumberOfCapturingGroups();
RE2::Arg *args = new RE2::Arg[argc];
RE2::Arg **argps = new RE2::Arg*[argc];
std::string *submatch = new std::string[argc];
for (int i = 0; i < argc; ++i) {
args[i] = &submatch[i];
argps[i] = &args[i];
}
bool ok = true;
for (auto _ : state) {
for (const char **strings = bench.strings; *strings; ++strings) {
ok = ok && RE2::FullMatchN(*strings, re, argps, argc);
}
}
if (!ok) {
state.SkipWithError("regexec failed");
}
add_counters(state, alg, bench, argc);
delete[] submatch;
delete[] argps;
delete[] args;
}
#else
void bench_regcomp_re2(benchmark::State &, const alg_t &, const bench_t &) {}
void bench_regexec_re2(benchmark::State &, const alg_t &, const bench_t &) {}
#endif
void bench_regcomp_t::operator()(benchmark::State &state, const alg_t &alg,
const bench_t &bench) const {
alg.engine == ENGINE_RE2C
? bench_regcomp_re2c(state, alg, bench)
: bench_regcomp_re2(state, alg, bench);
}
void bench_regexec_t::operator()(benchmark::State &state, const alg_t &alg,
const bench_t &bench) const {
alg.engine == ENGINE_RE2C
? bench_regexec_re2c(state, alg, bench)
: bench_regexec_re2(state, alg, bench);
}
+136
View File
@@ -0,0 +1,136 @@
#ifndef _RE2C_BENCHMRKS_COMMON_COMMON_
#define _RE2C_BENCHMRKS_COMMON_COMMON_
#include <benchmark/benchmark.h>
#include <string>
#include <vector>
#include <stdint.h>
enum engine_t {
ENGINE_RE2C,
ENGINE_RE2
};
struct alg_t {
const char *name;
engine_t engine;
int flags;
};
struct bench_t {
const char *name;
const char *regexp;
const char **strings;
};
// Need to define benchmarks as functors for benchmark::RegisterBenchmark.
struct bench_regcomp_t {
void operator()(benchmark::State&, const alg_t&, const bench_t&) const;
};
struct bench_regexec_t {
void operator()(benchmark::State&, const alg_t&, const bench_t&) const;
};
// RFC URI and HTTP
#define CRLF "[\\n]"
#define OCT "([0-9]|[1-9][0-9]|[1][0-9]{2}|[2][0-4][0-9]|[2][5][0-5])"
#define IPV4 "(" OCT "[.]" OCT "[.]" OCT "[.]" OCT ")"
#define H16 "[0-9a-fA-F]{1,4}"
#define LS32 "(" H16 ":" H16 "|" IPV4 ")"
#define IPV6 "((" H16 ":){6}" LS32 \
"|" "::(" H16 ":){5}" LS32 \
"|(" H16 ")?::(" H16 ":){4}" LS32 \
"|((" H16 ":){0,1}" H16 ")?::(" H16 ":){3}" LS32 \
"|((" H16 ":){0,2}" H16 ")?::(" H16 ":){2}" LS32 \
"|((" H16 ":){0,3}" H16 ")?::" H16 ":" LS32 \
"|((" H16 ":){0,4}" H16 ")?::" LS32 \
"|((" H16 ":){0,5}" H16 ")?::" H16 \
"|((" H16 ":){0,6}" H16 ")?::)"
#define IPVFUTURE "(v[0-9a-fA-F]+[.][-0-9a-zA-Z._~!$&'()*+,;=:]+)"
#define IPLITERAL "([[](" IPV6 "|" IPVFUTURE ")[\\]])"
#define REGNAME "(([-0-9a-zA-Z._~!$&'()*+,;=]|%[0-9a-fA-F]{2})*)"
#define HOST "(" IPLITERAL "|" IPV4 "|" REGNAME ")"
#define PORT "(:[0-9]*)?"
#define USERINFO "(([-a-zA-Z0-9._~!$&'()*+,;=:]|%[0-9a-fA-F]{2})*@)?"
#define SCHEME "([a-zA-Z][a-zA-Z0-9+.-]*):"
#define QUERY "([?]([-a-zA-Z0-9._~!$&'()*+,;=:@/?]|%[0-9a-fA-F]{2})*)?"
#define FRAGMENT "([#]([-a-zA-Z0-9._~!$&'()*+,;=:@/?]|%[0-9a-fA-F]{2})*)?"
#define PCHAR "([-0-9a-zA-Z._~!$&'()*+,;=:@]|%[0-9a-fA-F]{2})"
#define PATH_ABEMPTY "(/" PCHAR "*)*"
#define PATH_ABSOLUTE "/(" PCHAR "+(/" PCHAR "*)*)?"
#define PATH_ROOTLESS PCHAR "+(/" PCHAR "*)*"
#define PATH_EMPTY "([/]?)"
#define AUTHORITY "(" USERINFO HOST PORT ")"
#define HIER_PART "(//" AUTHORITY PATH_ABEMPTY "|" PATH_ABSOLUTE "|" PATH_ROOTLESS "|" PATH_EMPTY ")"
#define URI SCHEME HIER_PART QUERY FRAGMENT
#define ABSOLUTE_URI SCHEME HIER_PART QUERY
#define ORIGIN_FROM PATH_ABEMPTY QUERY
#define REQUEST_TARGET "(" AUTHORITY "|" ABSOLUTE_URI "|" ORIGIN_FROM "|([*]))"
#define METHOD "([-!#$%&'*+.^_`|~0-9a-zA-Z]+)"
#define HTTP_VERSION "(HTTP/[0-9][.][0-9])"
#define STATUS_CODE "([0-9]{3})"
#define REASON_PHRASE "([ \\t \\x1f-\\x7e\\x80-\\xff]*)"
#define REQUEST_LINE METHOD "[ ]" REQUEST_TARGET "[ ]" HTTP_VERSION CRLF
#define STATUS_LINE HTTP_VERSION "[ ]" STATUS_CODE "[ ]" REASON_PHRASE CRLF
#define FIELD_NAME "([-!#$%&'*+.^_`|~0-9a-zA-Z]+)"
#define FIELD_VCHAR "[\\x1f-\\x7e\\x80-\\xff]"
#define FIELD_CONTENT "(" FIELD_VCHAR "([ \\t]+" FIELD_VCHAR")?)"
#define FIELD_VALUE "(" FIELD_CONTENT "|" CRLF "[ \\t]+)*"
#define HEADER_FIELD "(" FIELD_NAME ":[ \\t]*" FIELD_VALUE "[ \\t]*)"
#define MESSAGE_HEAD "(" REQUEST_LINE "|" STATUS_LINE ")" "(" HEADER_FIELD CRLF ")*"
// simplified URI and HTTP
#define CHAR2 "[-._~%!$&'()*+,;=a-zA-Z0-9]"
#define SCHEME2 "([-+.a-zA-Z0-9]+):"
#define USERINFO2 "((" CHAR2 "|[:])+@)?"
#define HOST2 "((" CHAR2 "|[:[\\]])+)"
#define PORT2 "(:[0-9]*)?"
#define AUTHORITY2 USERINFO2 HOST2 PORT2
#define PATH2 "((" CHAR2 "|[:@/])*)"
#define QUERY2 "([?](" CHAR2 "|[:@?/])*)?"
#define FRAGMENT2 "([#](" CHAR2 "|[:@?/])*)?"
#define URI2 SCHEME2 "(//" AUTHORITY2 ")?" PATH2 QUERY2 FRAGMENT2
#define ABSOLUTE_URI2 SCHEME2 "(//" AUTHORITY2 PORT2 ")?" PATH2 QUERY2
#define ORIGIN_FROM2 "/" PATH2 QUERY2
#define REQUEST_TARGET2 "(" AUTHORITY2 "|" ABSOLUTE_URI2 "|" ORIGIN_FROM2 "|[*])"
#define HTTP_VERSION2 "(HTTP/[0-9][.][0-9])"
#define METHOD2 "([-._~%!$&'*+#^`|a-zA-Z0-9]+)"
#define REQUEST_LINE2 "(" METHOD2 "[ ]" REQUEST_TARGET2 "[ ]" HTTP_VERSION2 CRLF ")"
#define STATUS_LINE2 "(" HTTP_VERSION2 "[ ]([0-9]{3})[ ]([\\t \\x1f-\\x7e\\x80-\\xff]*)" CRLF ")"
#define HEADER_FIELD2 "([-._~%!$&'*+#^`|a-zA-Z0-9]+:[\\x1f-\\x7e\\x80-\\xff \\t\\n]*)"
#define MESSAGE_HEAD2 "(" REQUEST_LINE2 "|" STATUS_LINE2 ")" "(" HEADER_FIELD2 CRLF ")*"
// simplified IPv6
#define IPV62 "(((" H16 ":){0,7}" H16 ")?(::)?((" H16 ":){0,7}" H16 ")?)"
// simplified IPv4
#define IPV42 "([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})"
// date
#define DATE "(Mon|Tue|Wed|Thu|Fri|Sat|Sun)" \
"[ ]+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)" \
"[ ]+([0-9]{2})" \
"[ ]+([0-9]{4})" \
"[ ]+([0-9]{2}):([0-5][0-9]):[0-5][0-9](-[0-5][0-9])?(:[0-5][0-9])?" \
"[ ]+(([A-Z]{3})([+-]([0-5][0-9]):([0-5][0-9]))?)"
// simplified date
#define DATE2 "([a-zA-Z]+)[ ]+([a-zA-Z]+)[ ]+([0-9]+)[ ]+([0-9]+)[ ]+([0-9:-]+)[ ]+([A-Z0-9+-]+)"
// Gentoo package atom
#define PACKAGE_STR "([a-zA-Z0-9_+-]+)"
#define PACKAGE_NUM "([0-9]+)"
#define PACKAGE_VER "(" PACKAGE_NUM "([.]" PACKAGE_NUM ")*)"
#define PACKAGE_SFX1 "([a-z])?"
#define PACKAGE_SFX2 "((alpha|beta|pre|rc|p)" PACKAGE_NUM "?)"
#define PACKAGE_REV "(-r" PACKAGE_NUM ")?"
#define PACKAGE_ATOM PACKAGE_STR "/" PACKAGE_STR "-" PACKAGE_VER PACKAGE_SFX1 "(_" PACKAGE_SFX2 ")*" PACKAGE_REV
// simplified Gentoo package atom
#define PACKAGE_STR2 "([a-zA-Z0-9_/+-]+)"
#define PACKAGE_VER2 "([0-9.a-z_]+)"
#define PACKAGE_ATOM2 PACKAGE_STR2 "-" PACKAGE_VER2 PACKAGE_REV
#endif // _RE2C_BENCHMRKS_COMMON_COMMON_
File diff suppressed because it is too large. Load diff
+15
View File
@@ -0,0 +1,15 @@
#ifndef _RE2C_BENCHMRKS_COMMON_STRINGS_DATE_
#define _RE2C_BENCHMRKS_COMMON_STRINGS_DATE_
static const char *date_strings[] = {
"Mon Jan 01 2019 00:24:00 GMT",
"Tue Feb 02 2018 01:24:00 GMT",
"Wed Mar 03 2017 02:24:00 GMT",
"Thu Apr 04 2016 03:24:00 GMT",
"Fri May 05 2015 04:24:00 GMT",
"Sat Jun 06 2014 05:24:00 GMT",
"Sun Jul 07 2013 06:24:00 GMT",
NULL
};
#endif // _RE2C_BENCHMRKS_COMMON_STRINGS_DATE_
+305
View File
@@ -0,0 +1,305 @@
#ifndef _RE2C_BENCHMRKS_COMMON_STRINGS_HTTP_
#define _RE2C_BENCHMRKS_COMMON_STRINGS_HTTP_
static const char *http_strings[] = {
"HTTP/5.9 430 1wSXfgruktPZfhxm\n"
"X-Forwarded-For: client1, proxy1, proxy2\n"
"WWW-Authenticate: Basic\n"
"Connection: keep-alive\n"
"x-wap-profile: http://wap.samsungmobile.com/uaprof/SGH-I777.xml\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"X-Request-ID: f058ebd6-02f7-4d3f-942e-904344e8cde5\n"
"Cache-Control: max-age=3600\n"
"X-Att-Deviceid: GT-P7320/P7320XXLPG\n"
"Accept-Charset: utf-8\n"
"Max-Forwards: 10\n"
"Access-Control-Allow-Origin: *\n"
"P3P: CP=\"This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info.\"\n"
,
"HTTP/9.9 858 13rxsOgH\n"
"If-None-Match: \"737060cd8c284d8af7ad3082f209582d\"\n"
"X-Frame-Options: deny\n"
"Access-Control-Allow-Origin: *\n"
"Connection: keep-alive\n"
"Retry-After: 120\n"
"ETag: \"737060cd8c284d8af7ad3082f209582d\"\n"
"Content-Range: bytes 21010-47021/47022\n"
"Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"X-UA-Compatible: IE=edge\n"
"Content-Location: /index.htm\n"
"X-UA-Compatible: Chrome=1\n"
"Content-Language: da\n"
"Accept: text/plain\n"
"Host: en.wikipedia.org:8080\n"
"Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT\n"
"X-HTTP-Method-Override: DELETE\n"
"Warning: 199 Miscellaneous warning\n"
"Accept-Charset: utf-8\n"
"Content-Location: /index.htm\n"
"Content-Range: bytes 21010-47021/47022\n"
"Retry-After: 120\n"
,
"PATCH * HTTP/4.7\n"
"Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT\n"
"Content-Type: text/html; charset=utf-8\n"
"Proxy-Connection: keep-alive\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"X-Att-Deviceid: GT-P7320/P7320XXLPG\n"
"X-Forwarded-Host: en.wikipedia.org:8080\n"
,
"HTTP/0.9 510 ZvGc2\n"
"X-WebKit-CSP: default-src 'self'\n"
"Content-Location: /index.htm\n"
"X-UA-Compatible: Chrome=1\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"X-Forwarded-Host: en.wikipedia.org\n"
"Public-Key-Pins: max-age=2592000; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\";\n"
"Pragma: no-cache\n"
"Content-Location: /index.htm\n"
"Retry-After: Fri, 07 Nov 2014 23:59:59 GMT\n"
"Refresh: 5; url=http://www.w3.org/pub/WWW/People.html\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n"
"Connection: Upgrade\n"
"Content-Length: 51\n"
"Status: 200 OK\n"
"Strict-Transport-Security: max-age=16070400; includeSubDomains\n"
"Max-Forwards: 10\n"
"Age: 12\n"
"Alt-Svc: http/1.1=\"http2.example.com:8001\"; ma=7200\n"
"X-Att-Deviceid: GT-P7320/P7320XXLPG\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"X-WebKit-CSP: default-src 'self'\n"
"Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket\n"
"If-Range: \"737060cd8c284d8af7ad3082f209582d\"\n"
,
"HTTP/3.5 110 Aoq7A3pMGQq mgWvAz3GgU2Vlb\n"
"X-UIDH: ...\n"
"X-WebKit-CSP: default-src 'self'\n"
"If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT\n"
"From: user@example.com\n"
"Refresh: 5; url=http://www.w3.org/pub/WWW/People.html\n"
"Tk: ?\n"
"Connection: keep-alive\n"
"Origin: http://www.example-social-network.com\n"
"X-UIDH: ...\n"
"Accept-Charset: utf-8\n"
"Content-Type: application/x-www-form-urlencoded\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"DNT: 1 (Do Not Track Enabled)\n"
"Content-Encoding: gzip\n"
"If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT\n"
"Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n"
"Accept: text/plain\n"
,
"HTTP/3.6 975 SX UZSJdUJbVnFDeyLMzdyVb\n"
"X-Forwarded-Host: en.wikipedia.org\n"
"Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1\n"
"Expect: 100-continue\n"
"Content-Encoding: gzip\n"
"Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43\n"
"Content-Length: 348\n"
"Upgrade-Insecure-Requests: 1\n"
"Accept-Patch: text/example;charset=utf-8\n"
"Pragma: no-cache\n"
"Vary: *\n"
,
"HTTP/0.3 764 tfEoJrK 2p1F2Ao7OGUTxW\n"
"Connection: close\n"
"Referer: http://en.wikipedia.org/wiki/Main_Page\n"
"X-Content-Duration: 42.666\n"
"X-Request-ID: f058ebd6-02f7-4d3f-942e-904344e8cde5\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"Cache-Control: no-cache\n"
"Status: 200 OK\n"
"Access-Control-Allow-Origin: *\n"
,
"HTTP/9.7 828 9AvNbuZbvGKrCMzbUHOHwhQ4h\n"
"X-Content-Duration: 42.666\n"
"Trailer: Max-Forwards\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"Content-Type: text/html; charset=utf-8\n"
"Forwarded: for=192.0.2.43, for=198.51.100.17\n"
"If-Range: \"737060cd8c284d8af7ad3082f209582d\"\n"
"Pragma: no-cache\n"
"Accept-Language: en-US\n"
"Host: en.wikipedia.org:8080\n"
"If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\n"
"Content-Encoding: gzip\n"
"Range: bytes=500-999\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"Proxy-Authenticate: Basic\n"
"X-XSS-Protection: 1; mode=block\n"
"Allow: GET, HEAD\n"
"Connection: Upgrade\n"
"Retry-After: 120\n"
"X-UIDH: ...\n"
"Content-Type: text/html; charset=utf-8\n"
"Pragma: no-cache\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"Strict-Transport-Security: max-age=16070400; includeSubDomains\n"
"X-Frame-Options: deny\n"
"X-Forwarded-For: client1, proxy1, proxy2\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"WWW-Authenticate: Basic\n"
"Tk: ?\n"
"X-Content-Type-Options: nosniff\n"
"Accept-Language: en-US\n"
,
"HTTP/6.1 785 qED83aUkhrTKg7W3iQta4\n"
"Origin: http://www.example-social-network.com\n"
"x-wap-profile: http://wap.samsungmobile.com/uaprof/SGH-I777.xml\n"
"Connection: Upgrade\n"
"Vary: Accept-Language\n"
"Content-Disposition: attachment; filename=\"fname.ext\"\n"
"Warning: 199 Miscellaneous warning\n"
"Warning: 199 Miscellaneous warning\n"
"X-Forwarded-For: client1, proxy1, proxy2\n"
"Strict-Transport-Security: max-age=16070400; includeSubDomains\n"
"Link: </feed>; rel=\"alternate\"\n"
"Pragma: no-cache\n"
"X-Powered-By: PHP/5.4.0\n"
"Vary: Accept-Language\n"
"Accept: text/plain\n"
"Pragma: no-cache\n"
"Vary: Accept-Language\n"
"x-wap-profile: http://wap.samsungmobile.com/uaprof/SGH-I777.xml\n"
"Upgrade-Insecure-Requests: 1\n"
"X-Att-Deviceid: GT-P7320/P7320XXLPG\n"
"Tk: ?\n"
"Content-Location: /index.htm\n"
"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0\n"
"X-XSS-Protection: 1; mode=block\n"
"Content-Disposition: attachment; filename=\"fname.ext\"\n"
,
"PUT mdwishunysbgnqpk:uqfKE@154.41.44.150:8226 HTTP/7.1\n"
"Content-Type: application/x-www-form-urlencoded\n"
"From: user@example.com\n"
"Cache-Control: no-cache\n"
"Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket\n"
"DNT: 1 (Do Not Track Enabled)\n"
"Public-Key-Pins: max-age=2592000; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\";\n"
"Vary: Accept-Language\n"
"Accept: text/plain\n"
"Server: Apache/2.4.1 (Unix)\n"
"X-UIDH: ...\n"
"Cache-Control: no-cache\n"
"Tk: ?\n"
"Max-Forwards: 10\n"
"X-UA-Compatible: IE=edge\n"
"Max-Forwards: 10\n"
"Proxy-Authenticate: Basic\n"
"X-Forwarded-Proto: https\n"
"X-Content-Type-Options: nosniff\n"
"From: user@example.com\n"
"P3P: CP=\"This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info.\"\n"
"X-WebKit-CSP: default-src 'self'\n"
"X-Content-Duration: 42.666\n"
"TE: trailers, deflate\n"
"Forwarded: for=192.0.2.43, for=198.51.100.17\n"
"Connection: keep-alive\n"
"Expires: Thu, 01 Dec 1994 16:00:00 GMT\n"
"Date: Tue, 15 Nov 1994 08:12:31 GMT\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"Tk: ?\n"
,
"HTTP/7.3 997 DRQt ANhTIi\n"
"Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==\n"
"Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"If-Range: \"737060cd8c284d8af7ad3082f209582d\"\n"
"Location: http://www.w3.org/pub/WWW/People.html\n"
"Content-Length: 51\n"
"Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43\n"
"Alt-Svc: http/1.1=\"http2.example.com:8001\"; ma=7200\n"
"X-Content-Duration: 42.666\n"
"X-UIDH: ...\n"
"Content-Language: da\n"
"X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql\n"
"Host: en.wikipedia.org:8080\n"
"Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1\n"
"Range: bytes=500-999\n"
"Strict-Transport-Security: max-age=16070400; includeSubDomains\n"
"Accept-Charset: utf-8\n"
"Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT\n"
,
"HTTP/3.6 160 hE\n"
"P3P: CP=\"This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info.\"\n"
"X-Powered-By: PHP/5.4.0\n"
"Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1\n"
"Strict-Transport-Security: max-age=16070400; includeSubDomains\n"
"X-Frame-Options: deny\n"
"X-Requested-With: XMLHttpRequest\n"
"X-Powered-By: PHP/5.4.0\n"
"Retry-After: 120\n"
"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0\n"
"X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql\n"
"Content-Type: text/html; charset=utf-8\n"
"x-wap-profile: http://wap.samsungmobile.com/uaprof/SGH-I777.xml\n"
"P3P: CP=\"This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info.\"\n"
"Accept-Language: en-US\n"
"Via: 1.0 fred, 1.1 example.com (Apache/1.1)\n"
"Pragma: no-cache\n"
"Content-Type: application/x-www-form-urlencoded\n"
"X-Requested-With: XMLHttpRequest\n"
"TE: trailers, deflate\n"
"If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\n"
"Expect: 100-continue\n"
"Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1\n"
"Vary: *\n"
"X-Forwarded-Host: en.wikipedia.org\n"
"Host: en.wikipedia.org:8080\n"
"X-HTTP-Method-Override: DELETE\n"
"If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\n"
,
"HTTP/6.2 328 pNN5oXYb1EMAiYawAbGE4rvjBbQ\n"
"Allow: GET, HEAD\n"
"Server: Apache/2.4.1 (Unix)\n"
"Retry-After: Fri, 07 Nov 2014 23:59:59 GMT\n"
"Cache-Control: max-age=3600\n"
"X-Content-Type-Options: nosniff\n"
"Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket\n"
"Cache-Control: no-cache\n"
,
"GET https://249.225.169.119/qmpvnqskjdsgffmsqlwvrtckpjtx/xnaszgbskztlups/wuftfvlrw/nxkpghvpjanyvdok/hxbkqjlxjdklws/onecmivzmyrwznwantuqtpz/baetoveozlpg/dgmebtggvxowkmgpyzrakffcznrzte/odbpmrrlyvzerirapn/ihkcubbsihtvenhfpnvpqf HTTP/9.1\n"
"If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\n"
"Age: 12\n"
"X-WebKit-CSP: default-src 'self'\n"
"Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1\n"
"If-Range: \"737060cd8c284d8af7ad3082f209582d\"\n"
"TE: trailers, deflate\n"
"X-Content-Type-Options: nosniff\n"
"Accept-Language: en-US\n"
"Proxy-Connection: keep-alive\n"
"Status: 200 OK\n"
"Alt-Svc: http/1.1=\"http2.example.com:8001\"; ma=7200\n"
"Upgrade-Insecure-Requests: 1\n"
"Expect: 100-continue\n"
,
"HTTP/3.5 316 Bw05n9Cca\n"
"Pragma: no-cache\n"
,
"TRACE /kkyixdxiqyprpbwrqxrqmcz/kcepeaxtpiilfqacenwr/gkgruemrmvfeggastznmmaswf/zeysudldmbvmanstxpzsf/tdzor/jra/soygcoxezeuceiqybnsyzkrrsg/crny/jihmzdrvanvepaophpflwgpaluk/psnbrz HTTP/4.6\n"
"ETag: \"737060cd8c284d8af7ad3082f209582d\"\n"
"Proxy-Authenticate: Basic\n"
"Link: </feed>; rel=\"alternate\"\n"
"X-Forwarded-Proto: https\n"
"Front-End-Https: on\n"
"ETag: \"737060cd8c284d8af7ad3082f209582d\"\n"
"Host: en.wikipedia.org\n"
"X-Forwarded-Host: en.wikipedia.org:8080\n"
,
"HTTP/4.6 894 o4rjEil qL1gexedFU\tmKuGl8J\n"
"Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket\n"
"Date: Tue, 15 Nov 1994 08:12:31 GMT\n"
"X-XSS-Protection: 1; mode=block\n"
"Accept-Charset: utf-8\n"
"Allow: GET, HEAD\n"
"Age: 12345\n"
,
NULL
};
#endif // _RE2C_BENCHMRKS_COMMON_STRINGS_HTTP_
+13
View File
@@ -0,0 +1,13 @@
#ifndef _RE2C_BENCHMRKS_COMMON_STRINGS_IPV4_
#define _RE2C_BENCHMRKS_COMMON_STRINGS_IPV4_
static const char *ipv4_strings[] = {
"127.0.0.1",
"192.168.1.200",
"255.255.255.255",
"8.8.8.8",
"240.147.163.34",
NULL
};
#endif // _RE2C_BENCHMRKS_COMMON_STRINGS_IPV4_
+45
View File
@@ -0,0 +1,45 @@
#ifndef _RE2C_BENCHMRKS_COMMON_STRINGS_IPV6_
#define _RE2C_BENCHMRKS_COMMON_STRINGS_IPV6_
static const char *ipv6_strings[] = {
"fee2:586:10aa:fd03:37f:76ee:bed7:880",
"::fee2:586:fd03:37f:76ee:bed7:880",
"fee2::586:fd03:37f:76ee:bed7:880",
"fee2:586::fd03:37f:76ee:bed7:880",
"fee2:586:fd03::37f:76ee:bed7:880",
"fee2:586:fd03:37f::76ee:bed7:880",
"fee2:586:fd03:37f:76ee::bed7:880",
"fee2:586:fd03:37f:76ee:bed7::880",
"fee2:586:fd03:37f:76ee:bed7:880::",
"::586:fd03:37f:76ee:bed7:880",
"fee2::fd03:37f:76ee:bed7:880",
"fee2:fd03::37f:76ee:bed7:880",
"fee2:fd03:37f::76ee:bed7:880",
"fee2:fd03:37f:76ee::bed7:880",
"fee2:fd03:37f:76ee:bed7::880",
"fee2:fd03:37f:76ee:bed7:880::",
"::fd03:37f:76ee:bed7:880",
"fd03::37f:76ee:bed7:880",
"fd03:37f::76ee:bed7:880",
"fd03:37f:76ee::bed7:880",
"fd03:37f:76ee:bed7::880",
"fd03:fd03:37f:76ee:bed7::",
"::37f:76ee:bed7:880",
"fd03::76ee:bed7:880",
"fd03:37f::bed7:880",
"fd03:37f:76ee::880",
"fd03:37f:76ee:bed7::",
"::76ee:bed7:880",
"fd03::bed7:880",
"fd03:37f::880",
"fd03:37f:76ee::",
"::bed7:880",
"fd03::880",
"fd03:37f::",
"::bed7",
"fd03::",
"::",
NULL
};
#endif // _RE2C_BENCHMRKS_COMMON_STRINGS_IPV6_
+62
View File
@@ -0,0 +1,62 @@
#ifndef _RE2C_BENCHMRKS_COMMON_STRINGS_URI_
#define _RE2C_BENCHMRKS_COMMON_STRINGS_URI_
static const char *uri_strings[] = {
"http://240.147.163.34:2124/z/dibws/hkwfcdsvlghmmyd/ltiyxrfuam?fshxiix3zNzrBJNnuLDXnOruEmp4fX",
"http://yaad:60JmJOVECyQMmk@20.58.145.111:1700/gdnch/srdsabqbxp/nwsncxyawglw/bjojaxe",
"http://219.93.85.100:5179/q/y/pcraybhzqolbfrqummaly/chdgkbcqgdqzybvskovgwtn/gytxjczlwmfituesbikdimffr/xvqrmwufaaeqiufvkzvzqlvtape/nhrcdxivypkxcfb/qikdlrjrwkcrkdzjywwvuqvyjols/oonotquaxombhciqc/krpjzyvdmplsbdjpiyvwhpizvy?bjtsUNF2phdTxCYrtPLQH",
"ftp://vkfdbkyout.vfityckrzf.hsupobmbdg.juqncag.fxxi/eetvlflxtlmsccmifigfyfd/fqtdkczpvpvgn/ocfmanarai/pkrlrmnbarhxooirwau/qwtnjzkvwqrxeljnx/oknwgdxopk/palvzdkjuoiabytkar/efnzeqavdsxg/elmbmvkputgdkrspnasyxun/ctrahnuygpwncqqetwoelslynb?TNXVr7cKVbjo8KmKHSeGFFyVTb#7A66EXDTVm29hhLlp2uHyY59V2",
"file://rdahgrkzbo.iuzvfirjie.akfapgcaqu.gbeeb.wldnmxhghz/vdkvgcaunevwmvpotnt/fyifntckwqrwkimrlzicebcvqbter/aaqtkymaxovfowwrij/nghjhjimjsr/yxijmlsuiauintydtcnjxtctb/xjexokzpwfsyb/effopwkchzocekdabrqsz/oonlpdirtjrjkmvuxvjdwuhasx/anzxymcvtsjpshk/wgmnsjasfenczanarii?nLz6G8IQH",
"ftp://rjjxnbemcgqdirkrctmvq:5CkK@89.169.203.9/jgdsmyempoohzoravlkgcrauz/ofbi/fqfkzotvwdrv/icgvguluasosmtmktnxavbrfng/katligiisjhpn/jwcijbqivflntz/klmcce/xoanouaiyafj/u/uh?DOllNf#U9AY",
"http://djyqgnlpew.cuuvtx.neztaaxwqo.rndzdbtcof.wvnyhppngr/tnya?ks41JC0dn4e6pmrhzahh3qb6wCDzU",
"https://kafxctkpqr.kejsnnibia.cryxybfwvo.cbvikexrcg.irral/wxfnsxp/hgzflhwvpjisetnahpvdneyskej/otjdkwry/ozixeblclhufqoulcwwlpgooiy/ea/lbqlg/gnruaorx/dfreqzedtjmgnhrlbuigaeqzi/mjbkhyxhcyapgac?1THwzq2r5",
"file://244.65.252.87:1046/itnoaffeywuezfvmkctdaazi/fwyqfikj/rh/ufdyaypkbctoonzhzsnqdjkpobxzw/airnzrxwmacnocrmpa/dlffkuqe/lockgakqmhxgbc/zwpxzdujemfwizeatggs/hjizynljbllirwq/jgwnowwrirjehjwep?GgW8mIUZVv3xebOY3ySl4l",
"http:/ihcxyyghha/ayoexsg/zqf/ntkkyebqcppuraidwihl/krrjl/bqylpebqrzlgvghtqmfacwn/vjfigypqteuyqe/bdrvgweiakujik/fhogoaesbtjyqh/qetzjmr?qbe4edDAlRQXxH0kkW#agPl4osyN2tLvLt7T2QRDyKUb",
"https:/b/aiqcwonqswthnpspypbxjfydfetf/fmuydymzuejw/urqcdi/bzwxohtfhpembnisjswlyet/eeit/fpotyterxgrztodvjjezutqvrh/fieohgtwapiozzepkbjylydqqlicds/qkcgupvlprqivetowutbkwvlu/temuwujmqrcbjqfierqqnsgibh",
"http://86.195.159.88:8786/zqwzohkk/jgdfeoluytiskbpsji/hovdxaypl/viysqatkzdmroydhasziseqmo/zsokxoopaqvygopfkvd/kcwohfrsal/swgozklr/pjnrsksnjd/npjrqngoykqiddfngnvvg/pvmtpqkicj",
"http://inxotxc:h1tvU8rkAzL@jtlbsemydr.lnmkdgprcy.woejcsfypb.vycmuvlobz.refqsawrua/jwizpvtumwzp/t?EipGxsCek2ip#R3LNGrFgkuzy60",
"https:/izdhwoeaex/yifancchxsrnfjxliafgjav/zupznggsucsihzlwvkvwxihnyl/tyrout",
"http://zniekpcyhj.ajgg.enimtsqfgv.vhuvbkdwmi.tlqetyuvya:4096/qndto/llmrysrlbalnnltfxei/ynrmfk/zckhn/apuzmuxcgbuvv/qqymyuyyfedtubarp/vyexoedywlfrzqnfeu/wsqvs/jrvfmop/vlwfqjooajhriwydrfxkzhlfpobib?nbyBZnhIyau1U0OoUsZlMo2#Ot",
"file://iyqoggzfehha:D3lQGnWGVKVQRj5XlVsi6edJdu@55.133.243.122/oqizooy/cgydsxyhwbxc/tvoruimu/zcwcnyk?vgwHPlw3TPwk8iZ6BteN",
"file://gqfmqixlbaeb:U7QNl07GCODE@[3E07::]:8265/xjakjyhjwkaf/sdkhq/afwyjujqthmxrukxhbnh/gblizqsdshe/annd/xwhk/abv/efi/qhoyubtnybhzbuq/jgzxudizb",
"file://a:0Qjv756lK@rgdalivelm.zfhglcfmhi.zpvofrvfle.zhgxbkltuf:9115/ljzkzqhyyetzxwwgm/ftfknxwxrhorpl/jciiaxzfnaxqodvlddkuyqvw/sipdmcgpnufuavxoxowlkscr/dzkhxpwuvbeiphcexbrtyvguo/wobzwxsd/igh/johtkt/gxoiuohyvvlvnucvv/hxmaqzbug#kOeELSGhWgakSoCgsfDz8i",
"http://uflg.shu.wyakcdwh.ocixtaywuc.olo/digwvdhnyhepdsdfronpahzd/lox/lxruxebgyrjrggzt/jgatagcmnresebzrxcojpelecjbair/iuujxiwgtmemvlx/byplnmaqdkvlkpm/lslnxrnaknvupqqecrjonkcv/dyvmyhrwnzthlvrergluzcjmkdxgb/pucrhzpdp/ajeoocvmupxf?vebBkqQIwgCNVvtg4esoqUCPST5M#fsfmBggCpnfmR0kvH",
"http://wblezddguqcison:ziaT2Cs@vdckuauho.nuakkzojvu.dbnjyfrnxk/zratco/wnbpckbdlaoyuedkvgfwc/lrmkukulydnjnpuv/ayaawjkpcxtmxuhwmx/eucythronyknnjgd/niptpkbaneeadmhydoj/htbvhglitirniezousznbpcfokfaje/dlncinmmfmiuchqmrdn/pqcxvjg/hjanaj#LVVPGFIShMHjqGRiy",
"https://ofeqfzlwunufvavqfkmmrhmlslb:J7OA4c2hg@248.210.120.1:8289/geetgghbcrynhbvp/fqutclwgwjsfvkadrgpspgomsvyi/p?1TGfP",
"file://byvvrpfvulqaoyhdj:L9ln4SLJGQolSYoG6b@cidvpyemqt.asiunh.ls.ryoabgdfsj.idzbzxvosw/gwuzv/qgigladrdvirebdknqqqkyepjdsu/jeuz/zdjujpmdxrgzxiqvqcchbsntrxsl/otutbrzuznoqvomfwwlpjb/nziumj/hhfzlcwjumusruudtoxzehvvkm/jidbamvkyjxmh/oauydxxurafzhuevcrslbzqvdox/gqqszbmlkyhdk?Rd5R6",
"http://cg:gkVjlzui@25.159.213.165/byifaod/atsmatyigqhbzisue/plammyhj/kopytfdcjdiaspyoe?kniJwSTkbtU2TOSMGtvosYY",
"https://lgegaakmpknxnl:2G6bnG2ZHb7ypCMj08Ry@dneqpoazvy.ttunduuwde.s.qtgxcvahae.xwitsfafdk/ctluqripgfgsmyyyxl/ctqkelgrbgq/cshxwwz/pptkkafdh/yommtxddcnytoefflutmkgfxjlnxw/xnhlsykeqqcinreyvsbulpny?ibQeNiA5mZo34AzGOQOtnNk7TH",
"http://103.13.121.67/eoqddjyb/xjlejecrvdrdtdfry/pazcfqtzmdxzwldk/rcbczbfgtbgr/sp/majoylnfncveoroclyvydwz/azwrdnqu/qykwvlneeqtitsxbkafquslcdhtcjt/dugigiepoztvzprbdvjahzaxyk/cfpohfhsyqzv?b5Tmhpi93w6#Gm8LpLgmbKsM6ey3hBLzN7B5Cjc3U",
"file://ohidxhfuklcujxhwaneplwnrtafdms:7@[c9:24A:EF:aD:F:C4E6:Ac:9]:14/etcwrdfodgisop/mnxbzsellcimfbhfcxnqjk/tcousvlgknkcjlxuhezjuububo/wmknmyi/tuqnymadnapurahhbxb/nrbffmzadwascn/htfkhapegvwlesvpc/kamhlukivybyulltuxxkp/mwcjtzf/afoxizfsjtzpmfzlgfwddsbmqv?yl1EjLvkPCNNxCnzSYPTNdw#mtU4CN2ejAL",
"http://231.220.210.45/zgiaigvjwkhcjownb/agqksevqgcyihspjnrg/jbbvcbtpwpw/dpftpwgbucot/xicsx/xii/umefdahqrdmmr/z/ccypbkowabxsmtjdyddvdqmrrzw/gddzqjafdboxjsemncdya",
"ftp://mryip.zeysqszsdx.padszuq.igdeto.fiefkqo:5696/wneqbgvzcxc/ypmixakpwzcaz/sczxvkzxyjxoadeepfhiogtrguoxa/gbbyclepvmvwcnarpgwdphjzc/ryklwjkfhkmqe/ojmxbtagtwvqpbztyndfjhmfmuuo/vjrrpfevvzpwzamfwjatvlad/pwuthhhokoxlymrgliekytkshnnno/vyezdmvucvqjqriconw/yckx?U2HDne37nzRnDVTYBeo4E3Ow6",
"http:/qjokbcl/phrxxon/begtaaetynljvducrpcxfkbp/djawsfxquyuqrehdvboao/xxoektddmzujodiwsrfu",
"ftp://228.190.200.135/qninrtfzyiwqfigxtydyonwnq/whbyxez/pbngzsw/xqlkxeepnj/ejfwtaavikjmaqk/mowfhsyhtpsolwdkozdi/ftnhtczeyxvcalchawfpzthbdf/icvekpnbwvocolfpps/ilvwlezzgjqfhbfrwrvwgs/rmqrsoccqeinjcyncmdshumbcp?F1xIX7OS5Y1hnlh95dDk",
"http://222.100.150.244/jedjq/tifhvkruw/hwlevjywfx/hettutbsltjatopqsffookamj/ddvlhygbdtybzcldenovvcnncl/wzjyhnnilupjc/cpcsjpzxzbchgqnaz/nfa/vpijiofnloimfsvoargavoymkeb/vsksyjx#io4YWCIbMNa8uAy",
"http://dxxnvzfspng:3Ia1pm@woxpomrmnt.fmxmupapse.fbm.qjcswoopz.ubfnigsjyp:4641/ygaucnsppmpti/unicrhxddhweibyqoxhsezhvkfs/ccrewwlpijgpomywkt/ldnnbniazqiwesuuel/ehvngaobyfj/igcmhjskqdhsxmbqirlpsaoubc/bmmczgdzhetehajtcrywsqc/kdvezrbphprwlsqsnw/ttgizewqshnbjf/phjebast#xKP3Ek",
"http://zizoikhxd:8Sg3grS3u5w5IsanKn2@2.86.121.243/gmgkxeahiaahxnmxwlwylvvfyax/iz/mpjxipqfhxfaniinzig/muhxjamekrbbd/idapkowgexyumcubzdzexwczouxoxi/hpzfdypgbvmmz/qgfcceuy/nqwjaoeydylqjkmvcfv/oqmlu/ushgfnhizyangugnkogki",
"http://ogjnhcwvr:YE8zSGWcgk@pv.zkaypqrwvc.zynlwqu.qoxbsdtvyi.jfedvvpary/opyo/pnzitpwuzwktevpmsnajqehf/ongvjakt/utdjzst/nvjy/tmzzpvqyvkorgs/ftxzkackxlief/eiqfsaffkfrkhp/veqmhybdejifbjdmxh/nsapgh#IQ",
"http:/qqatcohyntibkhnqswswyxpd/rwtpuxihjtu/ztd/ir/mnnrpauyuhcsiebldlfbpxuwktn/qark/lqklqexmataxkosnorunv/zhsuljssuxwztbrhddkwhn/dmxeubivcvmudjadayyqifakk/fdbknmxmjdxdw?T53Xv2Np8YEi1F3LbYFri",
"ftp://93.203.59.192/cuytxqxxsmmutmhkjaetfg/pixqzfejbtvq/hmchovbkkuisuqqfndwrcxe/tibwoimtefh/rbuwlbplvmxmkcbvwvorkvcjo/bmbgdbdykhtsgyrihnyeazwa/ydnvbpxhbdkzlqnvqh/yyzqgmcmbsnlmplbhtia/nlghhfztoeedyfzgcghmbfadv/xpinmjgq#czNZiHO8",
"http://82.56.201.96/cjsib/qklcxeqbsrcoh#tSKwpP",
"ftp://nvnzqrpguirjddcxefyhlkezydwwg:AcuDlBDS1xEWde@180.36.59.108/nimswbaeugke/yyxohlw/wcbscprbptgzlsqhncpoqbwmt/kjj/pfifainijsausdkresmc/jb/dmzbwzuxfoswbhtgqhmxeuimr/g/jbvduwoqeuwpegyuxqvjraynni/fbqhjgcfgfhmciodxcjcp?Uab4rQN11Z6KiF2",
"ftp://ywcruqjfg.vwnwzelrow.hgmbrjflyk.frzrmqjxbk.tbjddejcni:480/hpyjhpfyevzv/xbvtaktnlfcbgbmj/jdfbedteagikfytqysimkqyfj/nfvnvqjfue/ehzktfqalz/cfysjoioecxtpwcvjh/fwoeixudfpjsygvjto/hydn/ovapakvpevwtrg/rokpnjnkdmzolzscnmtbdiv?2FuSuebgl96xjtv4TzQ",
"ftp:/k/waodexdpwvmur/zaguwbqvavwmuzvyhrgao/sojsf/doeuanvtcugycxkghnxnibqijdukpv/ufnqjighmwxlwkhjui/afbduapmd/fdikoepuzsgrupdmmmcxa/tnmgazereumjbpeitciyrzyzqgpoe?CdKAsjYS#OQaNcaA2PK9KTe2Pa2zwO",
"http://qnhrxhqgur.tvbftk.crruupgxec.toaznijfex.cclemgdwiz/f/baprklcamrkrquleripsz/s/ogezdjzasopsrfgv/tfatmyt/ycsebcsqyvpjxvtvgfksrmquo#JAypKFZR",
"https://yjqjucgqnr.csrebunggb/vcddnfigrkuoe/n/nrxyyngebsbhphgwbzuwpbhk/xpvfplzyrux/hlssfpjylpoougckhqzdm/fwkiwqj/yfotuvtnhkhtkevrolovrhddh/okvzef/mvfaolqnvnkyxuwjopitnlr/vnjwwxbeuodarcpvjojfpymkswlj#aXpK4cMVYMtLyIjX8iHlzBhhDgoMrL",
"http://q:FZ4YPI4syGXwbpNxy5@246.105.84.81:3644/omk/bafcocdyqndkgjqc/fqeaommsuosdyfondrlpjjhgpeme/wipoqedke/fgck/vailhtflcfiosnbwnfvk/lgwxuywp/utovjtpbplnqdnp/hkigzvfczyosxzycvjpeswvpx/azcleshiltmwplrqkqimbdmh?vrUvfPCxQFIr15k",
"file://253.59.27.32:4951/aasko/ytyaqqeaklvpneg/pkrpjvhuoswgcpjah/ltmfnkfmayzpmvksilw/vwe/ccgfb/yeifqgzmirjpaoaly/ovaiwpenskwknhnazitues/pefiokocd/kcyzpliy?R0HRKrSJV29u9MZUs9H8L7o4#EJFi",
"http:/ndfpgzlpvpcc/azgtdwrtugaslneunppnwhltrmnt/zqlyduihoytopqrjbe/sputkujimpsznavrpnwmuwssyaaens?xAgN8m0H2eXO0Ok14eMd7",
"https://187.163.186.205/lewocvpbdnhk/zpzecxp/bgakaceifuodjjk/vtrwqkadjsbwkslpbenlcmpncxyj/rqyyptrazhyty/bq/zfdzwhmqwuuqoqqlgvrk/eqyskursnsrxlxddhthylcylqximjm/aztmrvuihh/rliiqwlmxmni#HOdsfyB40dxMLayoJWXrO4U5MlS",
"file://qsnyikskrg.oimlfvrnlz.rdbsfhbxoh.fffzsomuue.vw:5272/twbpbjpiznzjndrughaxku/acnoympxnjzvudvhdiqgysnuqpkv/djswnzogkh/gpgmhgkkokkovlnouzeoa/kzeaoejpjqviiinncpxaurgkfdgthw/qplcfe/oaevryer/kzsqtflgjwcquivq/eignzixtgpiitqaylwguyrdojnkf/hobacblieh",
"ftp://unkkasfkhv.pwifchllmr.ncegrrlows.mg.uuivggceqk:7081/kcbnjbjufinsksfvffyhcbx/lcnndvse/xrwtwaihscvokcbrzqdimtxmvo/c/x/roqejyqrmmtlpocgna/tqxeklnappcrbcgfibsryg/rhellecjikmahjcykhn/rjzizj/taptfgymanxuarwdy?we2OQ1TzRUImWYvo9QR#v04oMYio9j7fFVreequt",
"ftp://58.224.205.87/druqmabvzqjyyjkztfcvcskzafjizb/ny/ksuwaqnytlxwylmmqsaxmy/vtaftwcatzdztjgbclkabsxvpms/ngijrefqhqzrfjsdpjgnlfalylal/ckcfpisayebolufnwhwxfbnuamsa/kgniymo/lqfslyokefbknjdyzconvybndmaf/torszcxcgehiatrlfilsambdpvsygh#r2",
"http://pfaq.aapffjymu/gjrrttpxivfhdvzf/eesvqglcnyvoo/olpkcqyk/lrspsmqrmisgewisddszbmccnx/hgpq/fhwvurjpflfvjnaifzvlikjkqfyh/zfjkdqjcbggropjgrwufdnybu/uxpbtjeculadltoczfadsf?QN1AAYUFMcHHl",
"http://rdbfmbaf:GrYcY4u29MIh@zgfqtbewiz.cgfgzqgpnp.pwfslpyfzs.yndq.ryn/xaubwwwskxajwtmooz/wexfwfmc/ksbqjuesya/irkfredpblhqlofankgv/kdmjaazfgwnqqvycufmazpy/pkejffkwqehzzigfmpghurj/ghruhwkcwljeyjqx/hlcytprgyGdAym#bluC5",
"https://en.wikipedia.org",
"http://re2c.org",
"https://google.com",
NULL
};
#endif // _RE2C_BENCHMRKS_COMMON_STRINGS_URI_
+390
View File
@@ -0,0 +1,390 @@
#!/usr/bin/env python3
import argparse
import json
import math
import sys
from collections import OrderedDict
plot_preamble = """
\\documentclass[tikz]{standalone}
\\usepackage[utf8]{inputenc}
\\usepackage{amsmath, amssymb, amsfonts}
\\usepackage{xcolor}
\\usepackage{tikz, pgfplots, pgfplotstable}
\\usepackage{pifont}
\\definecolor{colorX}{HTML}{A1CAF1}
\\definecolor{colorY}{HTML}{FBCEB1}
"""
# Use Comic Neue font.
plot_font_comicneue = """
\\usepackage{comicneue}
\\usepackage[T1]{fontenc}
\\renewcommand{\\familydefault}{\\sfdefault}
"""
# Use Computer Modern Bright font.
plot_font_cmbright = """
\\usepackage{cmbright}
\\usepackage[T1]{fontenc}
\\renewcommand{\\familydefault}{\\sfdefault}
"""
# Counterintuitively, 'assume math mode' tricks pgfmathprintnumber into not
# setting math mode, which is needed because Comic Neue does not support math.
#
# Use 'fixed relative' number format with very high precision (the numbers have
# been previously rounded to a few non-zero digits in the fractional part, so
# the trailing zeroes will will not be printed).
plot_begin = """
\\begin{document}
\\def\\plotwidth{%lfin}
\\def\\barwidth{%lfin}
\\pgfplotsset{styleX/.style={
font=\\scriptsize,
xbar,
axis y line*=none,
axis x line=none,
y=0.12in,
width=\\plotwidth*1.15,
bar width=\\barwidth,
xshift=\\xplotshift,
yshift=\\yplotshift,
xmax=\\xmax,
xmin=0,
ymax=0.7,
ymin=0.3 - \\nrows,
ytick=data,
ytick style={draw=none},
yticklabels=\\empty,
title=\\empty,
clip=false,
visualization depends on={x > \\xmax \\as \\xoverflow},
visualization depends on={x > \\xmax ? -x + \\xmax : 0 \\as \\xshift},
nodes near coords={
\\ifdim \\xoverflow pt=1pt \\!\\ding{220}\\! \\scriptsize \\fi
\\pgfmathprintnumber[assume math mode=true]{\\pgfplotspointmeta}
},
nodes near coords style={shift={(axis direction cs:\\xshift,0)}},
nodes near coords style={/pgf/number format/.cd,
fixed relative,
precision = 10,
1000 sep = {\\,}
},%s}}
"""
plot_labels_and_title = """
yticklabels from table={\\table}{algo},
every axis title/.style={below %s, at={(-0.08in,0)}},
title=\\title,
"""
plot_begin_picture = """
\\begin{tikzpicture}
\\begin{scope}[xshift=-0.2in, yshift=%sin * 0.75]
%s
\\end{scope}
"""
plot_middle = """
\\def\\xplotshift{%lfin}
\\def\\yplotshift{%lfin}
\\def\\nrows{%d},
\\def\\title{%s},
\\def\\xmax{%lf}
\\pgfplotstableread {%s} \\table
\\begin{axis}[styleX,%s]
\\clip(current axis.south west) rectangle(current axis.north east);
\\addplot[fill=%s] table[x=value, y expr=-\\coordindex] from \\table;
\\end{axis}
"""
plot_end_picture = """
\\end{tikzpicture}
"""
plot_end = """
\\end{document}
"""
VARIANTS = ['dfa_aot', 'dfa_jit', 'nfa']
def parse_args():
variants = ', '.join(VARIANTS)
parser = argparse.ArgumentParser()
parser.add_argument("input", help="input JSON file")
parser.add_argument("output", help="output TeX file")
parser.add_argument("--variant",
help="variant of the benchmark, one of %s" % variants)
parser.add_argument("--relative-to",
help="output CPU time relative to the specified algorithm")
parser.add_argument("--font",
help="use the specified font (supported fonts: cmbright, comicneue)")
args = parser.parse_args()
if args.variant not in VARIANTS:
sys.exit("please specify --variant (possible values: %s)" % variants)
return args
# Generate benchmark title from benchmark name.
def gen_title(oldname, remove_suffix):
if remove_suffix:
# cut off the last sub-word after the dash
oldname = oldname[:oldname.rfind("-")]
# Name begins with a letter, so it must be a plain language word.
if oldname[0].isalpha():
return oldname
# Name begins with something else than a letter, treat it as a regexp and
# render as a TeX math formula. This requires adding a few metacharacters.
newname = ""
for char in oldname:
if char in "{*+?":
# Repetition counters must be in superscript.
newname += "^"
newname += char
return "$\\boldsymbol{" + newname + "}$"
# Find index of a group which algorithm contains the given string (stem).
def index_of_algo(group, stem):
if stem == None:
return 0;
for i in range(len(group)):
(algo, _, _, _, _) = group[i]
if stem in algo:
return i
return 0
# Time format: keep integer part precise, round fractional part relative to the
# exponent (similar to PGFPLOTS's "fixed relative, precision = 2" numer format,
# but doesn't round integer part). This is to reduce visual noise on the plot.
#
# Examples: 1004, 195, 13, 3.8, 0.85, 0.017, 0.0048
#
def time_format(time):
order = math.floor(math.log(time, 10))
if order > 0:
return '%.0lf'
else:
return '%%.%dlf' % (-order + 1)
class Params:
def __init__(self, args):
self.barwidth = 0.08
if args.variant == 'dfa_aot':
self.override_params_dfa_aot()
elif args.variant == 'dfa_jit':
self.override_params_dfa_jit()
elif args.variant == 'nfa':
self.override_params_nfa()
self.font = ''
if args.font == 'comicneue':
self.font = plot_font_comicneue
elif args.font == 'cmbright':
self.font = plot_font_cmbright
elif args.font:
sys.exit('error: unsupported font: "%s"' % font)
if args.relative_to: # override only if set
self.relative_to = args.relative_to
def override_params_dfa_aot(self):
self.plotwidth = 1.5
self.xshift = 2 * self.plotwidth
self.header = """
\\node[anchor=west] (x0) at (0.15in,0) {\\small\\bf{gcc (time)}};
\\node[anchor=west] (x1) at (1.65in,0) {\\small\\bf{gcc (size)}};
\\node[anchor=west] (x2) at (3.15in,0) {\\small\\bf{clang (time)}};
\\node[anchor=west] (x3) at (4.65in,0) {\\small\\bf{clang (size)}};
"""
self.title_suffix = True
self.relative_to = None
self.title_annotate = False
self.global_styles = ""
self.local_styles = plot_labels_and_title % 'left'
def override_params_dfa_jit(self):
self.plotwidth = 2.7
self.xshift = self.plotwidth
self.header = """
\\node[anchor=west] (x0) at (0.15in,0) {\\small\\bf{regcomp (time)}};
\\node[anchor=west] (x1) at (2.85in,0) {\\small\\bf{regexec (time)}};
"""
self.title_suffix = True
self.relative_to = ''
self.title_annotate = False
self.global_styles = ""
self.local_styles = plot_labels_and_title % 'left'
def override_params_nfa(self):
self.plotwidth = 2.5
self.xshift = self.plotwidth + 1
self.header = ""
self.only_1st_col_with_labels = False
self.title_suffix = False
self.relative_to = 'LG'
self.title_annotate = True
self.global_styles = plot_labels_and_title % 'right'
self.local_styles = ""
# Split benchmarks into groups by regexp (the first component of the name).
# If the relative mode is on, normalize CPU time by the time of the first
# benchmark in each group.
#
# Expected JSON fomat:
# {
# "benchmarks": [
# {
# "name": <string>,
# ["cpu_time": <number>,]
# ["bin_size": <number>,]
# ["captures": <number>,]
# ["regsize": <number>,] ...
# }, ...
# ], ...
# }
#
def group_benchmarks(benchmarks, params):
benchcount = len(benchmarks)
groups = OrderedDict()
for bench in benchmarks:
name, algo = bench['name'].split('_')
cputime = bench['cpu_time'] if 'cpu_time' in bench else None
binsize = bench['bin_size'] if 'bin_size' in bench else None
captures = bench['captures'] if 'captures' in bench else None
regsize = bench['regsize'] if 'regsize' in bench else None
groups.setdefault(name, []).append(
(algo, cputime, binsize, captures, regsize))
maxtime = 0
avgtime = 0
maxsize = 0
avgsize = 0
maxrows = 0
nbench = 0
benchgroups = OrderedDict()
for name in groups:
group = groups[name]
relto = index_of_algo(group, params.relative_to)
(_, cputime0, binsize0, captures, regsize) = group[relto]
timetbl = None
if cputime0 != None:
table = 'algo value\n'
for (algo, time, _, _, _) in group:
time = time / (cputime0 if params.relative_to != None else 1)
maxtime = max(maxtime, time)
avgtime += time
table += ('{%s} ' + time_format(time) + '\n') % (algo, time)
timetbl = table
sizetbl = None
if binsize0 != None:
table = 'algo value\n'
for (algo, _, size, _, _) in group:
maxsize = max(maxsize, size)
avgsize += size
table += '{%s} %lf\n' % (algo, size)
sizetbl = table
title = gen_title(name, params.title_suffix)
nrows = len(group)
benchgroups[name] = (title, timetbl, sizetbl, nrows, regsize, captures)
nbench += nrows
maxrows = max(maxrows, nrows)
avgtime /= nbench
avgsize /= nbench
factor = 10 if params.relative_to != None else 3
maxtime = min(maxtime, factor * avgtime)
maxsize = min(maxsize, factor * avgsize)
params.plotheight = 0.15 + maxrows * params.barwidth * 0.75
params.maxtime = maxtime
params.maxsize = maxsize
return benchgroups
# Generate a Tikz picture with a PGF plot for each benchmark group. Crop
# very long bars, so that they do not squash other bars to the left.
def generate_plot(benchgroups, params):
plot = plot_preamble
plot += params.font
plot += plot_begin % (params.plotwidth, params.barwidth, params.global_styles)
plot += plot_begin_picture % (params.plotheight, params.header)
i = 0
for name, benchgroup in benchgroups.items():
even = i % 2 == 0
i += 1
(title, timetbl, sizetbl, nrows, regsize, captures) = benchgroup
xshift = 0 if even else params.xshift
yshift = -params.plotheight * (i if even else i - 1)
title = '\\textbf{%s}' % title
if params.title_annotate and regsize != None and captures != None:
title += ' \\, (%d symbol%s, %d capture%s)' % (
regsize, 's' if regsize > 1 else '',
captures, 's' if captures > 1 else '')
# Generate CPU time plots.
if timetbl != None:
plot += plot_middle % (xshift, yshift, nrows, title, params.maxtime,
timetbl, params.local_styles if even else '', 'colorX')
# Generate binary size plots.
if sizetbl != None:
xshift += params.plotwidth
plot += plot_middle % (xshift, yshift, nrows, title, params.maxsize,
sizetbl, '', 'colorY')
plot += plot_end_picture
plot += plot_end
return plot
def main():
args = parse_args()
with open(args.input) as f:
input = json.load(f)
params = Params(args)
groups = group_benchmarks(input['benchmarks'], params)
plot = generate_plot(groups, params)
with open(args.output, 'w') as f:
f.write(plot)
if __name__ == "__main__":
main()
+2
View File
@@ -0,0 +1,2 @@
bin/**
data/*/big
+255
View File
@@ -0,0 +1,255 @@
set(BENCHMARKS
"00__http_rfc7230"
"01__http_simple"
"02__uri_rfc3986"
"03__uri_simple"
"04__apache_log"
"05__datetime"
"06__email"
"07__ipv4"
"10__alt1_2"
"11__alt1_4"
"12__alt1_8"
"13__alt2_2"
"14__alt2_4"
"15__alt2_8"
"16__alt4_2"
"17__alt4_4"
"18__alt4_8"
"20__cat2_0"
"21__cat2_4"
"22__cat2_8"
"23__cat4_0"
"24__cat4_2"
"25__cat4_4"
"26__cat8_0"
"27__cat8_1"
"28__cat8_2"
"30__rep_cat_5_3_2"
"31__rep_cat_13_11_7"
"32__rep_cat_23_19_17"
"33__rep_alt_5_3_2"
"34__rep_alt_13_11_7"
"35__rep_alt_23_19_17"
"36__rep_5_rep_3_rep_2"
"37__rep_13_rep_11_rep_7"
"38__rep_23_rep_19_rep_17"
)
set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(ENG_DIR "${CMAKE_CURRENT_BINARY_DIR}/engines")
set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen")
set(BIN_DIR "${CMAKE_CURRENT_BINARY_DIR}/bin")
set(PREGEN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pregen")
set(GEN "")
# kleenex
file(MAKE_DIRECTORY "${ENG_DIR}/kleenex/")
file(MAKE_DIRECTORY "${GEN_DIR}/kleenex/")
set(KLEENEX "${ENG_DIR}/kleenex/kexc")
add_custom_command(
OUTPUT "${KLEENEX}"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/engines/kleenex/getkleenex.sh"
WORKING_DIRECTORY "${ENG_DIR}/kleenex/"
)
# Masked benchmarks for which Kleenex either generates very large output
# (tens of megabytes of C code), or even causes out of memory condition.
set(KLEENEX_MASKED
"34__rep_alt_13_11_7"
"35__rep_alt_23_19_17"
"37__rep_13_rep_11_rep_7"
"38__rep_23_rep_19_rep_17"
)
list(JOIN KLEENEX_MASKED "|" KLEENEX_MASKED_REGEXP)
set(KLEENEX_BENCHMARKS ${BENCHMARKS})
list(FILTER KLEENEX_BENCHMARKS EXCLUDE REGEX "${KLEENEX_MASKED_REGEXP}")
foreach(bench ${KLEENEX_BENCHMARKS})
set(src_file "${SRC_DIR}/kleenex/${bench}.kex")
set(gen_file "${GEN_DIR}/kleenex/${bench}.c")
set(pregen_file "${PREGEN_DIR}/kleenex/${bench}.c")
# optionally regenerate kleenex benchmarks if RE2C_REGEN_BENCHMARKS is set
if(RE2C_REGEN_BENCHMARKS)
file(RELATIVE_PATH rel_src_file "${CMAKE_CURRENT_BINARY_DIR}" "${src_file}")
file(RELATIVE_PATH rel_gen_file "${CMAKE_CURRENT_BINARY_DIR}" "${gen_file}")
add_custom_command(
OUTPUT "${gen_file}"
COMMAND "${KLEENEX}" compile "${rel_src_file}" --srcout "${rel_gen_file}" --act=false --la=true
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${gen_file}" "${pregen_file}"
DEPENDS "${src_file}" "${KLEENEX}"
)
else()
add_custom_command(
OUTPUT "${gen_file}"
COMMAND "${CMAKE_COMMAND}" -E copy "${pregen_file}" "${gen_file}"
DEPENDS "${pregen_file}"
)
endif()
list(APPEND GEN "${gen_file}")
endforeach()
# ragel
file(MAKE_DIRECTORY "${ENG_DIR}/ragel/")
file(MAKE_DIRECTORY "${GEN_DIR}/ragel/")
set(RAGEL "${ENG_DIR}/ragel/ragel7")
add_custom_command(
OUTPUT "${RAGEL}"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/engines/ragel/getragel7.sh"
WORKING_DIRECTORY "${ENG_DIR}/ragel/"
)
foreach(bench ${BENCHMARKS})
set(src_file "${SRC_DIR}/ragel/${bench}.rl")
set(gen_file "${GEN_DIR}/ragel/${bench}.c")
set(pregen_file "${PREGEN_DIR}/ragel/${bench}.c")
# optionally regenerate ragel benchmarks if RE2C_REGEN_BENCHMARKS is set
if(RE2C_REGEN_BENCHMARKS)
file(RELATIVE_PATH rel_src_file "${CMAKE_CURRENT_BINARY_DIR}" "${src_file}")
file(RELATIVE_PATH rel_gen_file "${CMAKE_CURRENT_BINARY_DIR}" "${gen_file}")
add_custom_command(
OUTPUT "${gen_file}"
COMMAND "${RAGEL}" "-G2" "${rel_src_file}" -o "${rel_gen_file}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${gen_file}" "${pregen_file}"
DEPENDS "${src_file}" "${RAGEL}"
)
else()
add_custom_command(
OUTPUT "${gen_file}"
COMMAND "${CMAKE_COMMAND}" -E copy "${pregen_file}" "${gen_file}"
DEPENDS "${pregen_file}"
)
endif()
list(APPEND GEN "${gen_file}")
endforeach()
# re2c
file(MAKE_DIRECTORY "${ENG_DIR}/re2c/")
file(MAKE_DIRECTORY "${GEN_DIR}/re2c/")
set(RE2C "${CMAKE_BINARY_DIR}/re2c")
set(RE2C3 "${ENG_DIR}/re2c/re2c3")
add_custom_command(
OUTPUT "${RE2C3}"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/engines/re2c/getre2c3.sh"
WORKING_DIRECTORY "${ENG_DIR}/re2c/"
)
set(RE2C_FLAGS "--reusable" "--tags" "--no-generation-date" "--no-version")
set(COMMON_RE2C
"${SRC_DIR}/re2c/common.re"
"${SRC_DIR}/re2c/include/fill.re"
"${SRC_DIR}/re2c/include/fill_email.re"
"${SRC_DIR}/re2c/include-eof/fill.re"
"${SRC_DIR}/re2c/include-eof/fill_email.re"
)
# deprecated algorithms were removed after re2c-3.0
set(DEPRECATED_ALGS "tdfa0" "stadfa")
foreach(bench ${BENCHMARKS})
foreach(eof "" "-eof")
foreach(alg "tdfa1" "tdfa0" "stadfa")
set(src_file "${SRC_DIR}/re2c/${bench}.re")
set(gen_file "${GEN_DIR}/re2c/${bench}${eof}-${alg}.c")
set(pregen_file "${PREGEN_DIR}/re2c/${bench}${eof}-${alg}.c")
# always regenerate re2c benchmarks, except for deprecated algorithms
if(RE2C_REGEN_BENCHMARKS OR NOT (alg IN_LIST DEPRECATED_ALGS))
# for deprecated algorithms use re2c-3.0
if(alg IN_LIST DEPRECATED_ALGS)
set(re2c_for_gen "${RE2C3}")
else()
set(re2c_for_gen "${RE2C}")
endif()
file(RELATIVE_PATH rel_src_file "${CMAKE_CURRENT_BINARY_DIR}" "${src_file}")
file(RELATIVE_PATH rel_gen_file "${CMAKE_CURRENT_BINARY_DIR}" "${gen_file}")
file(RELATIVE_PATH rel_inc_path "${CMAKE_CURRENT_BINARY_DIR}" "${SRC_DIR}/re2c/include${eof}")
set(re2c_flags ${RE2C_FLAGS} "-I" "${rel_inc_path}")
if("${alg}" STREQUAL "tdfa0")
set(re2c_flags ${re2c_flags} "--no-lookahead")
elseif("${alg}" STREQUAL "stadfa")
set(re2c_flags ${re2c_flags} "--stadfa")
endif()
add_custom_command(
OUTPUT "${gen_file}"
COMMAND "${re2c_for_gen}" ${re2c_flags} "${rel_src_file}" -o "${rel_gen_file}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${gen_file}" "${pregen_file}"
DEPENDS "${src_file}" ${COMMON_RE2C} "${re2c_for_gen}"
)
else()
add_custom_command(
OUTPUT "${gen_file}"
COMMAND "${CMAKE_COMMAND}" -E copy "${pregen_file}" "${gen_file}"
DEPENDS "${pregen_file}"
)
endif()
list(APPEND GEN "${gen_file}")
endforeach()
endforeach()
endforeach()
# binaries
set(OBJ "")
set(BIN "")
set(CFLAGS "-O3" "-I" "${SRC_DIR}")
set(COMMON_SRC "${SRC_DIR}/common.h")
file(MAKE_DIRECTORY "${BIN_DIR}/kleenex/")
file(MAKE_DIRECTORY "${BIN_DIR}/ragel/")
file(MAKE_DIRECTORY "${BIN_DIR}/re2c/")
foreach(gen_file ${GEN})
foreach(compiler "gcc" "clang")
string(REGEX REPLACE "^${GEN_DIR}(.+)\.c$" "${BIN_DIR}\\1-${compiler}" bin_file "${gen_file}")
set(obj_file "${bin_file}.o")
add_custom_command(
OUTPUT "${bin_file}"
COMMAND "${compiler}" ${CFLAGS} -c "${gen_file}" -o "${obj_file}"
COMMAND "${compiler}" ${CFLAGS} "${obj_file}" -o "${bin_file}"
DEPENDS "${gen_file}" ${COMMON_SRC}
)
list(APPEND OBJ "${obj_file}")
list(APPEND BIN "${bin_file}")
endforeach()
endforeach()
# helper function to transform list
function(regex_replace_list regexp replace var)
set(result "")
foreach(arg ${ARGN})
string(REGEX REPLACE "${regexp}" "${replace}" x "${arg}")
list(APPEND result "${x}")
endforeach()
set(${var} "${result}" PARENT_SCOPE)
endfunction()
# input data
set(DAT)
# Some benchmarks share the same data, like 03__uri_simple and 02__uri_rfc3986.
regex_replace_list("^[0-9]+__([^_]+).*" "\\1" INPUTS ${BENCHMARKS})
list(REMOVE_DUPLICATES INPUTS)
foreach(input ${INPUTS})
set(src_dir "${CMAKE_CURRENT_SOURCE_DIR}/data/${input}")
set(dst_dir "${CMAKE_CURRENT_BINARY_DIR}/data/${input}")
file(GLOB script "${CMAKE_CURRENT_SOURCE_DIR}/data/gen.py")
add_custom_command(
OUTPUT "${dst_dir}/small"
COMMAND "${CMAKE_COMMAND}" -E copy "${src_dir}/small" "${dst_dir}/small"
DEPENDS "${src_dir}/small"
)
add_custom_command(
OUTPUT "${dst_dir}/big"
COMMAND "${script}"
DEPENDS "${script}" "${dst_dir}/small"
WORKING_DIRECTORY "${dst_dir}"
)
list(APPEND DAT "${dst_dir}/small" "${dst_dir}/big")
endforeach()
add_custom_target(bench_submatch_dfa_aot ALL DEPENDS ${BIN} ${DAT})
# benchmark scripts
set(srcdir "${CMAKE_CURRENT_SOURCE_DIR}")
set(builddir ".")
configure_file(run.py.in run.py @ONLY)
# override default clean command to keep engines (ragel, kleenex)
set_directory_properties(PROPERTY
CLEAN_NO_CUSTOM On
ADDITIONAL_CLEAN_FILES "${GEN};${OBJ};${BIN};${DAT}"
)
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 The KMC authors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+201
View File
@@ -0,0 +1,201 @@
SRC_DIR = $(srcdir)/src
ENG_DIR = engines
GEN_DIR = gen
PREGEN_DIR = $(srcdir)/pregen
BIN_DIR = bin
DAT_DIR = data
CFLAGS = -O3 -I $(SRC_DIR)
RAGEL = $(ENG_DIR)/ragel/ragel7
KLEENEX = $(ENG_DIR)/kleenex/kexc
RE2C3 = $(ENG_DIR)/re2c/re2c3
RE2C = $(top_builddir)/re2c
RE2C_FLAGS_COMMON = --reusable --tags --no-generation-date --no-version
RE2C_FLAGS = $(RE2C_FLAGS_COMMON) -I $(SRC_DIR)/re2c/include
RE2C_FLAGS_EOF = $(RE2C_FLAGS_COMMON) -I $(SRC_DIR)/re2c/include-eof
BENCHMARKS = \
00__http_rfc7230 \
01__http_simple \
02__uri_rfc3986 \
03__uri_simple \
04__apache_log \
05__datetime \
06__email \
07__ipv4 \
\
10__alt1_2 \
11__alt1_4 \
12__alt1_8 \
13__alt2_2 \
14__alt2_4 \
15__alt2_8 \
16__alt4_2 \
17__alt4_4 \
18__alt4_8 \
\
20__cat2_0 \
21__cat2_4 \
22__cat2_8 \
23__cat4_0 \
24__cat4_2 \
25__cat4_4 \
26__cat8_0 \
27__cat8_1 \
28__cat8_2 \
\
30__rep_cat_5_3_2 \
31__rep_cat_13_11_7 \
32__rep_cat_23_19_17 \
33__rep_alt_5_3_2 \
34__rep_alt_13_11_7 \
35__rep_alt_23_19_17 \
36__rep_5_rep_3_rep_2 \
37__rep_13_rep_11_rep_7 \
38__rep_23_rep_19_rep_17
COMMON_SRC = $(SRC_DIR)/common.h
GEN_RAGEL = $(patsubst %, $(GEN_DIR)/ragel/%.c, $(BENCHMARKS))
BIN_RAGEL = $(patsubst $(GEN_DIR)%.c, $(BIN_DIR)%, $(GEN_RAGEL))
COMMON_RAGEL = $(COMMON_SRC) $(SRC_DIR)/ragel/common.c
GEN_RE2C_TDFA1 = $(patsubst %, $(GEN_DIR)/re2c/%-tdfa1.c, $(BENCHMARKS))
GEN_RE2C_EOF_TDFA1 = $(patsubst %, $(GEN_DIR)/re2c/%-eof-tdfa1.c, $(BENCHMARKS))
GEN_RE2C = \
$(GEN_RE2C_TDFA1) \
$(GEN_RE2C_EOF_TDFA1)
GEN_RE2C3_TDFA0 = $(patsubst %, $(GEN_DIR)/re2c/%-tdfa0.c, $(BENCHMARKS))
GEN_RE2C3_EOF_TDFA0 = $(patsubst %, $(GEN_DIR)/re2c/%-eof-tdfa0.c, $(BENCHMARKS))
GEN_RE2C3_STADFA = $(patsubst %, $(GEN_DIR)/re2c/%-stadfa.c, $(BENCHMARKS))
GEN_RE2C3_EOF_STADFA = $(patsubst %, $(GEN_DIR)/re2c/%-eof-stadfa.c, $(BENCHMARKS))
GEN_RE2C3 = \
$(GEN_RE2C_TDFA0) \
$(GEN_RE2C_EOF_TDFA0) \
$(GEN_RE2C3_STADFA) \
$(GEN_RE2C3_EOF_STADFA)
BIN_RE2C = $(patsubst $(GEN_DIR)%.c, $(BIN_DIR)%, $(GEN_RE2C) $(GEN_RE2C3))
COMMON_RE2C = \
$(COMMON_SRC) \
$(SRC_DIR)/re2c/common.re \
$(SRC_DIR)/re2c/include/fill.re \
$(SRC_DIR)/re2c/include/fill_email.re \
$(SRC_DIR)/re2c/include-eof/fill.re \
$(SRC_DIR)/re2c/include-eof/fill_email.re
# Masked benchmarks for which Kleenex either generates very large output
# (tens of megabytes of C code), or even causes out of memory condition.
KLEENEX_MASKED = \
34__rep_alt_13_11_7 \
35__rep_alt_23_19_17 \
37__rep_13_rep_11_rep_7 \
38__rep_23_rep_19_rep_17
GEN_KLEENEX = $(patsubst %, $(GEN_DIR)/kleenex/%.c, \
$(filter-out $(KLEENEX_MASKED), $(BENCHMARKS)))
BIN_KLEENEX = $(patsubst $(GEN_DIR)%.c, $(BIN_DIR)%, $(GEN_KLEENEX))
GEN = $(GEN_RAGEL) $(GEN_RE2C) $(GEN_RE2C3) $(GEN_KLEENEX)
BIN_ = $(BIN_RAGEL) $(BIN_RE2C) $(BIN_KLEENEX)
BIN_GCC = $(patsubst %, %-gcc, $(BIN_))
BIN_CLANG = $(patsubst %, %-clang, $(BIN_))
BIN = $(BIN_GCC) $(BIN_CLANG)
OBJ = $(patsubst %, %.o, $(BIN))
# Some benchmarks share the same data, like 03__uri_simple and 02__uri_rfc3986.
DAT = $(patsubst %, $(DAT_DIR)/%/big, \
$(sort $(foreach bench, $(BENCHMARKS), \
$(word 2, $(subst _, , $(bench))))))
all-local: $(BIN) $(DAT)
# always regenerate re2c benchmarks (except for deprecated algorithms)
$(GEN_RE2C_TDFA1): $(GEN_DIR)/%-tdfa1.c: $(SRC_DIR)/%.re $(COMMON_RE2C) $(RE2C)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RE2C) $(RE2C_FLAGS) $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/re2c/$(@F) ; then cp -f $@ $(PREGEN_DIR)/re2c/$(@F) ; fi
$(GEN_RE2C_EOF_TDFA1): $(GEN_DIR)/%-eof-tdfa1.c: $(SRC_DIR)/%.re $(COMMON_RE2C) $(RE2C)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RE2C) $(RE2C_FLAGS_EOF) $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/re2c/$(@F) ; then cp -f $@ $(PREGEN_DIR)/re2c/$(@F) ; fi
# optionally regenerate ragel, kleenex and re2c-3.0 benchmarks
# (TDFA(0) and staDFA algorithms were removed in re2c versions after 3.0)
if REGEN_BENCHMARKS
$(GEN_RE2C3_TDFA0): $(GEN_DIR)/%-tdfa0.c: $(SRC_DIR)/%.re $(COMMON_RE2C) $(RE2C3)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RE2C3) $(RE2C_FLAGS) --no-lookahead $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/re2c/$(@F) ; then cp -f $@ $(PREGEN_DIR)/re2c/$(@F) ; fi
$(GEN_RE2C3_EOF_TDFA0): $(GEN_DIR)/%-eof-tdfa0.c: $(SRC_DIR)/%.re $(COMMON_RE2C) $(RE2C3)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RE2C3) $(RE2C_FLAGS_EOF) --no-lookahead $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/re2c/$(@F) ; then cp -f $@ $(PREGEN_DIR)/re2c/$(@F) ; fi
$(GEN_RE2C3_STADFA): $(GEN_DIR)/%-stadfa.c: $(SRC_DIR)/%.re $(COMMON_RE2C) $(RE2C3)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RE2C3) $(RE2C_FLAGS) --stadfa $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/re2c/$(@F) ; then cp -f $@ $(PREGEN_DIR)/re2c/$(@F) ; fi
$(GEN_RE2C3_EOF_STADFA): $(GEN_DIR)/%-eof-stadfa.c: $(SRC_DIR)/%.re $(COMMON_RE2C) $(RE2C3)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RE2C3) $(RE2C_FLAGS_EOF) --stadfa $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/re2c/$(@F) ; then cp -f $@ $(PREGEN_DIR)/re2c/$(@F) ; fi
$(GEN_RAGEL): $(GEN_DIR)/%.c: $(SRC_DIR)/%.rl $(COMMON_RAGEL) $(RAGEL)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(RAGEL) -G2 $< -o $@
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/ragel/$(@F) ; then cp -f $@ $(PREGEN_DIR)/ragel/$(@F) ; fi
$(GEN_KLEENEX): $(GEN_DIR)/%.c: $(SRC_DIR)/%.kex $(KLEENEX)
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)$(KLEENEX) compile $< --srcout $@ --act=false --la=true
$(AM_V_at)if ! cmp -s $@ $(PREGEN_DIR)/kleenex/$(@F) ; then cp -f $@ $(PREGEN_DIR)/kleenex/$(@F) ; fi
else
$(GEN_RAGEL) $(GEN_RE2C3) $(GEN_KLEENEX): $(GEN_DIR)/%: $(PREGEN_DIR)/%
$(AM_V_at)mkdir -p $(@D)
$(AM_V_GEN)cp -f $< $@
endif
$(BIN_GCC): $(BIN_DIR)/%-gcc: $(GEN_DIR)/%.c
$(AM_V_at)mkdir -p $(@D)
$(AM_V_at)gcc $(CFLAGS) -c -o $@.o $<
$(AM_V_GEN)gcc $(CFLAGS) -o $@ $@.o
$(BIN_CLANG): $(BIN_DIR)/%-clang: $(GEN_DIR)/%.c
$(AM_V_at)mkdir -p $(@D)
$(AM_V_at)clang $(CFLAGS) -c -o $@.o $<
$(AM_V_GEN)clang $(CFLAGS) -o $@ $@.o
$(DAT): $(DAT_DIR)/%/big: $(DAT_DIR)/%/small
$(AM_V_at)mkdir -p $(@D) && cp $(srcdir)/$(@D)/small $(@D)
$(AM_V_GEN)( cd $(@D) && ../../$(srcdir)/data/gen.py )
$(KLEENEX):
$(AM_V_at)mkdir -p $(@D) && cp $(srcdir)/engines/kleenex/getkleenex.sh $(@D)
$(AM_V_GEN)( cd $(@D) && ./getkleenex.sh )
$(RAGEL):
$(AM_V_at)mkdir -p $(@D) && cp $(srcdir)/engines/ragel/getragel7.sh $(@D)
$(AM_V_GEN)( cd $(@D) && ./getragel7.sh )
$(RE2C3):
$(AM_V_at)mkdir -p $(@D) && cp $(srcdir)/engines/re2c/getre2c3.sh $(@D)
$(AM_V_GEN)( cd $(@D) && ./getre2c3.sh )
clean-local:
$(AM_V_at)rm -f $(GEN) $(OBJ) $(BIN) $(DAT)
+7
View File
@@ -0,0 +1,7 @@
The following benchmarks have been taken from the Kleenex repository
(https://github.com/diku-kmc/kleenexlang) and are licensed under the MIT
license (together with the data generators):
- apache_log
- datetime_to_json
- email
@@ -0,0 +1,17 @@
a
b
aa
bb
aaaa
bbbb
aaaaaaaa
bbbbbbbb
aaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
@@ -0,0 +1,15 @@
ab
ba
aabb
bbaa
aaaabbbb
bbbbaaaa
aaaaaaaabbbbbbbb
bbbbbbbbaaaaaaaa
aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -0,0 +1,13 @@
abab
baba
aabbaabb
bbaabbaa
aaaabbbbaaaabbbb
bbbbaaaabbbbaaaa
aaaaaaaabbbbbbbbaaaaaaaabbbbbbbb
bbbbbbbbaaaaaaaabbbbbbbbaaaaaaaa
aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -0,0 +1,813 @@
99.121.81.108 - - [23/Mar/2015:17:07:24 -0700] "GET /Documents/Ali.htm HTTP/1.1" 200 8449 "http://www.google.com/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=5&ved=0CDkQFjAE&url=http%3A%2F%2Fredlug.com%2FDocuments%2FAli.htm&ei=PKoQVb-gJsnZsASzgYLgDA&usg=AFQjCNEyOmJJeANb79rhMnwQEi73tJtBgg" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0; Touch)"
99.121.81.108 - - [23/Mar/2015:17:07:24 -0700] "GET /cwi.css HTTP/1.1" 404 88 "http://redlug.com/Documents/Ali.htm" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0; Touch)"
31.184.238.152 - - [23/Mar/2015:17:09:08 -0700] "GET /logs/access.log HTTP/1.1" 200 604 "http://www.theknot.com/wedding/baclofen-and-delivery" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:17:09:55 -0700] "GET /logs/access.log HTTP/1.1" 200 865 "http://orderpepcidquickshipping.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 OPR/19.0.1326.63"
141.101.31.80 - - [23/Mar/2015:17:13:19 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0"
141.101.31.80 - - [23/Mar/2015:17:13:19 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1"
141.101.31.80 - - [23/Mar/2015:17:13:20 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1"
141.101.31.80 - - [23/Mar/2015:17:13:20 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"
141.101.31.80 - - [23/Mar/2015:17:13:20 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"
141.101.31.80 - - [23/Mar/2015:17:13:21 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; WOW64; U; ru) Presto/2.10.289 Version/12.02"
141.101.31.80 - - [23/Mar/2015:17:13:21 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; WOW64; U; ru) Presto/2.10.289 Version/12.02"
187.24.242.229 - - [23/Mar/2015:17:17:33 -0700] "GET /logs/access.log HTTP/1.1" 200 707 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
180.76.5.65 - - [23/Mar/2015:17:18:42 -0700] "GET /temp/ HTTP/1.1" 200 748 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
31.184.238.152 - - [23/Mar/2015:17:19:39 -0700] "GET /logs/access.log HTTP/1.1" 200 3012 "http://buyglucophageonlinequickshipping.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:17:20:26 -0700] "GET /logs/access.log HTTP/1.1" 200 3276 "http://buy-actos-without-prescription.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68"
193.226.34.229 - - [23/Mar/2015:17:22:00 -0700] "GET /logs/access.log HTTP/1.1" 200 935 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
193.226.34.229 - - [23/Mar/2015:17:22:01 -0700] "GET /Documents/Ali.htm HTTP/1.1" 200 8448 "http://redlug.com/logs/access.log" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
216.108.237.129 - - [23/Mar/2015:17:23:47 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 200 207560 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
193.226.34.227 - - [23/Mar/2015:17:25:11 -0700] "GET /logs/access.log HTTP/1.1" 200 1036 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
193.226.34.227 - - [23/Mar/2015:17:25:11 -0700] "GET /Documents/Ali.htm HTTP/1.1" 200 8448 "http://redlug.com/logs/access.log" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:17:30:07 -0700] "GET /logs/access.log HTTP/1.1" 200 4752 "http://www.theknot.com/wedding/without-and-estrace" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:17:30:51 -0700] "GET /logs/access.log HTTP/1.1" 200 5012 "http://naproxen-500mg-order-safely.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
107.23.45.196 - - [23/Mar/2015:17:32:37 -0700] "GET / HTTP/1.1" 200 9589 "http://redlug.com/" "Mozilla/5.0 (compatible; DuckDuckGo-Favicons-Bot/1.0; +http://duckduckgo.com)"
188.165.15.10 - - [23/Mar/2015:17:36:11 -0700] "GET /sitemap/0310Bins.htm HTTP/1.1" 404 88 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
31.184.238.152 - - [23/Mar/2015:17:40:46 -0700] "GET /logs/access.log HTTP/1.1" 200 5640 "http://buyprevacid15mgonlinebe.soup.io" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
141.101.31.80 - - [23/Mar/2015:17:41:27 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; WOW64; Edition Yx) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [23/Mar/2015:17:41:27 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11"
141.101.31.80 - - [23/Mar/2015:17:41:27 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11"
141.101.31.80 - - [23/Mar/2015:17:41:28 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1"
141.101.31.80 - - [23/Mar/2015:17:41:28 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1"
141.101.31.80 - - [23/Mar/2015:17:41:29 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.1.1084.5409 Chrome/19.1.1084.5409 Safari/536.5"
141.101.31.80 - - [23/Mar/2015:17:41:29 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.1.1084.5409 Chrome/19.1.1084.5409 Safari/536.5"
31.184.238.152 - - [23/Mar/2015:17:41:32 -0700] "GET /logs/access.log HTTP/1.1" 200 7522 "http://amoxapine-50mg-order-online.over-blog.com" "Mozilla/5.0 (Windows NT 5.1; rv:26.0) Gecko/20100101 Firefox/26.0"
188.116.52.19 - - [23/Mar/2015:17:42:11 -0700] "GET /logs/access.log HTTP/1.1" 200 1451 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
69.250.121.218 - - [23/Mar/2015:17:46:33 -0700] "GET /socview/SV0302TroublesReview.htm HTTP/1.1" 200 3182 "https://www.google.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
69.250.121.218 - - [23/Mar/2015:17:46:33 -0700] "GET /cwi.css HTTP/1.1" 404 89 "http://redlug.com/socview/SV0302TroublesReview.htm" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
180.76.6.136 - - [23/Mar/2015:17:48:42 -0700] "GET /images/ HTTP/1.1" 200 1939 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
157.55.39.135 - - [23/Mar/2015:17:51:04 -0700] "GET /Assorted/VidalReview.htm HTTP/1.1" 200 4223 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
2.218.128.170 - - [23/Mar/2015:17:51:09 -0700] "GET /images/QUBAntiFascism031112.jpg HTTP/1.1" 200 15209 "https://www.google.co.uk/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:17:51:21 -0700] "GET /logs/access.log HTTP/1.1" 200 9156 "http://orderflomaxbr.soup.io" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [23/Mar/2015:17:52:05 -0700] "GET /logs/access.log HTTP/1.1" 200 9364 "http://orderfluticasoneonlineca.soup.io" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"
104.128.138.146 - - [23/Mar/2015:17:53:23 -0700] "GET /logs/access.log HTTP/1.1" 200 2371 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
203.130.249.17 - - [23/Mar/2015:17:58:00 -0700] "GET /logs/access.log HTTP/1.1" 200 2391 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:02:09 -0700] "GET /logs/access.log HTTP/1.1" 200 10061 "http://acyclovir400mgv51.aircus.com" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:02:51 -0700] "GET /logs/access.log HTTP/1.1" 200 10307 "http://permethrin-buy-no-prescription.snack.ws" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.15"
157.55.39.83 - - [23/Mar/2015:18:03:27 -0700] "GET /paper2004JD/0410Protests.htm HTTP/1.1" 200 2137 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
141.101.31.80 - - [23/Mar/2015:18:09:13 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"
141.101.31.80 - - [23/Mar/2015:18:09:14 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; Win64; x64; Edition Yx) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [23/Mar/2015:18:09:14 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; Win64; x64; Edition Yx) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [23/Mar/2015:18:09:15 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Nichrome/self/19"
141.101.31.80 - - [23/Mar/2015:18:09:15 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Nichrome/self/19"
141.101.31.80 - - [23/Mar/2015:18:09:16 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.64"
141.101.31.80 - - [23/Mar/2015:18:09:16 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.64"
54.209.60.63 - - [23/Mar/2015:18:11:43 -0700] "GET /LabHist/1911Linen.htm HTTP/1.1" 200 2583 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25"
74.216.26.213 - - [23/Mar/2015:18:12:43 -0700] "GET /paperarticles/0302YaW.htm HTTP/1.1" 200 4077 "https://www.google.ca/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
74.216.26.213 - - [23/Mar/2015:18:12:44 -0700] "GET /cwi.css HTTP/1.1" 404 88 "http://redlug.com/paperarticles/0302YaW.htm" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:12:54 -0700] "GET /logs/access.log HTTP/1.1" 200 12994 "http://buytrihexyphenidyl.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [23/Mar/2015:18:13:41 -0700] "GET /logs/access.log HTTP/1.1" 200 13208 "http://ordercloxacillinonline.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:24:09 -0700] "GET /logs/access.log HTTP/1.1" 200 13456 "http://ordervermox100mgfastshipping.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:25:18 -0700] "GET /logs/access.log HTTP/1.1" 200 13717 "http://orderneurontin300mgwithoutscript.snack.ws" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
134.249.140.212 - - [23/Mar/2015:18:25:48 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"
134.249.140.212 - - [23/Mar/2015:18:25:48 -0700] "GET //wp-login.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows NT 6.1; rv:37.0) Gecko/20100101 Firefox/37.0"
134.249.140.212 - - [23/Mar/2015:18:25:49 -0700] "GET / HTTP/1.1" 200 9589 "-" "Mozilla/5.0 (Windows NT 6.1; rv:37.0) Gecko/20100101 Firefox/37.0"
134.249.140.212 - - [23/Mar/2015:18:25:50 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (compatible; bingbot/3.0-alpha; +http://www.bing.com/bingbot.htm)"
134.249.140.212 - - [23/Mar/2015:18:25:50 -0700] "GET //admin/index.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (compatible; bingbot/3.0-alpha; +http://www.bing.com/bingbot.htm)"
134.249.140.212 - - [23/Mar/2015:18:25:50 -0700] "GET //bitrix/admin/index.php?lang=en HTTP/1.1" 404 73 "-" "Mozilla/5.0 (compatible; bingbot/3.0-alpha; +http://www.bing.com/bingbot.htm)"
134.249.140.212 - - [23/Mar/2015:18:25:50 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (compatible; bingbot/3.0-alpha; +http://www.bing.com/bingbot.htm)"
134.249.140.212 - - [23/Mar/2015:18:25:50 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (compatible; bingbot/3.0-alpha; +http://www.bing.com/bingbot.htm)"
134.249.140.212 - - [23/Mar/2015:18:25:51 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (compatible; bingbot/3.0-alpha; +http://www.bing.com/bingbot.htm)"
100.43.81.129 - - [23/Mar/2015:18:28:36 -0700] "GET /logs/access_150122.log HTTP/1.1" 200 1928717 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
24.21.73.217 - - [23/Mar/2015:18:30:43 -0700] "GET /Documents/Ali.htm HTTP/1.1" 200 8450 "https://www.google.com/" "Mozilla/5.0 (Linux; Android 5.0; SM-G900V Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36"
24.21.73.217 - - [23/Mar/2015:18:30:44 -0700] "GET /cwi.css HTTP/1.1" 404 89 "http://redlug.com/Documents/Ali.htm" "Mozilla/5.0 (Linux; Android 5.0; SM-G900V Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36"
54.174.244.172 - - [23/Mar/2015:18:31:21 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.174.244.172 - - [23/Mar/2015:18:31:21 -0700] "GET /documents/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.174.244.172 - - [23/Mar/2015:18:31:21 -0700] "GET /wardoc/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /paper2004jd/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /bins/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /war/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /index.html HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /election07/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /socyouth/ HTTP/1.1" 404 73 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.174.244.172 - - [23/Mar/2015:18:31:21 -0700] "GET /socview/ HTTP/1.1" 200 13443 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.152.206.230 - - [23/Mar/2015:18:31:21 -0700] "GET /temp/ HTTP/1.1" 200 4828 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.174.244.172 - - [23/Mar/2015:18:31:21 -0700] "GET /images/ HTTP/1.1" 200 16831 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
54.175.5.159 - - [23/Mar/2015:18:33:30 -0700] "GET /Assorted/StrikerstoSmyth.htm HTTP/1.1" 200 2960 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:35:43 -0700] "GET /logs/access.log HTTP/1.1" 200 18692 "http://buyhydrochlorothiazide5mgcheap.snack.ws" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:36:28 -0700] "GET /logs/access.log HTTP/1.1" 200 18949 "http://ordermobicquickshipping.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"
141.101.31.80 - - [23/Mar/2015:18:36:38 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.1634 Safari/535.19 YE"
141.101.31.80 - - [23/Mar/2015:18:36:39 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.12 (KHTML, like Gecko) Maxthon/3.0 Chrome/18.0.966.0 Safari/535.12"
141.101.31.80 - - [23/Mar/2015:18:36:39 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.12 (KHTML, like Gecko) Maxthon/3.0 Chrome/18.0.966.0 Safari/535.12"
141.101.31.80 - - [23/Mar/2015:18:36:40 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322)"
141.101.31.80 - - [23/Mar/2015:18:36:40 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322)"
141.101.31.80 - - [23/Mar/2015:18:36:41 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0"
141.101.31.80 - - [23/Mar/2015:18:36:41 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0"
188.165.15.10 - - [23/Mar/2015:18:36:41 -0700] "GET /Election07/News.htm HTTP/1.1" 200 1405 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
80.67.212.62 - - [23/Mar/2015:18:38:09 -0700] "GET /logs/access.log HTTP/1.1" 200 3566 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
204.28.110.118 - - [23/Mar/2015:18:40:18 -0700] "GET /images/2006/OmaghChe.jpg HTTP/1.1" 200 21025 "https://www.google.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
192.42.116.16 - - [23/Mar/2015:18:41:02 -0700] "GET / HTTP/1.1" 200 1273 "http://hundejo.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36"
155.133.19.224 - - [23/Mar/2015:18:42:55 -0700] "GET /logs/access.log HTTP/1.1" 200 3064 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:18:46:32 -0700] "GET /logs/access.log HTTP/1.1" 200 21934 "http://ordercasodexnoscript.forumcircle.com" "Mozilla/5.0 (Windows NT 5.1; rv:26.0) Gecko/20100101 Firefox/26.0"
31.184.238.152 - - [23/Mar/2015:18:47:19 -0700] "GET /logs/access.log HTTP/1.1" 200 22151 "http://zantac-buy-no-rx.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
62.210.205.155 - - [23/Mar/2015:18:50:37 -0700] "GET /logs/access_130901.log HTTP/1.1" 404 88 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
62.210.205.155 - - [23/Mar/2015:18:50:37 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
100.43.81.131 - - [23/Mar/2015:18:51:53 -0700] "GET /pdf/women.pdf HTTP/1.1" 200 34646 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
31.184.238.152 - - [23/Mar/2015:18:57:28 -0700] "GET /logs/access.log HTTP/1.1" 200 23052 "http://buy-furoxone-no-rx.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 OPR/19.0.1326.63"
31.184.238.152 - - [23/Mar/2015:18:58:15 -0700] "GET /logs/access.log HTTP/1.1" 200 23320 "http://xlmevacor10mg.forumcircle.com" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
141.101.31.80 - - [23/Mar/2015:19:04:50 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19 CoolNovo/2.0.3.55"
141.101.31.80 - - [23/Mar/2015:19:04:50 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/17.0 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:19:04:51 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/17.0 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:19:04:51 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)"
141.101.31.80 - - [23/Mar/2015:19:04:52 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)"
141.101.31.80 - - [23/Mar/2015:19:04:52 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
141.101.31.80 - - [23/Mar/2015:19:04:53 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
5.135.148.171 - - [23/Mar/2015:19:06:09 -0700] "GET / HTTP/1.1" 200 1273 "http://hvd-store.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36"
212.83.131.201 - - [23/Mar/2015:19:07:33 -0700] "GET /logs/access.log HTTP/1.1" 200 3450 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
176.8.89.30 - - [23/Mar/2015:19:07:49 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://minedroid.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
176.8.89.30 - - [23/Mar/2015:19:07:49 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://www.to2ko.ru/" "Opera/9.01 (Windows NT 5.1; U; en)"
176.8.89.30 - - [23/Mar/2015:19:07:49 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://evehost.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
176.8.89.30 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://minedroid.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
176.8.89.30 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://www.to2ko.ru/" "Opera/9.01 (Windows NT 5.1; U; en)"
176.8.89.30 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://evehost.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
46.119.118.191 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://nanoagro.net/" "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1)"
176.8.89.30 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://www.to2ko.ru/" "Opera/9.01 (Windows NT 5.1; U; en)"
176.8.89.30 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://evehost.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
176.8.89.30 - - [23/Mar/2015:19:07:50 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://minedroid.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
46.119.118.191 - - [23/Mar/2015:19:07:51 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://nanoagro.net/" "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1)"
46.119.118.191 - - [23/Mar/2015:19:07:52 -0700] "GET /Documents/PunkUSA.htm HTTP/1.1" 200 13496 "http://nanoagro.net/" "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1)"
31.184.238.152 - - [23/Mar/2015:19:08:15 -0700] "GET /logs/access.log HTTP/1.1" 200 28140 "http://buy-stavudine-40mg-cheap.snack.ws" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.15"
31.184.238.152 - - [23/Mar/2015:19:08:58 -0700] "GET /logs/access.log HTTP/1.1" 200 28353 "http://gravatar.com/minocycline100mgqo" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
157.55.39.83 - - [23/Mar/2015:19:11:12 -0700] "GET /Election/031106Song.htm HTTP/1.1" 200 1088 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
76.0.172.58 - - [23/Mar/2015:19:13:41 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 200 207560 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
76.0.172.58 - - [23/Mar/2015:19:13:42 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 206 32768 "http://redlug.com/pdf/che_sos.pdf" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
76.0.172.58 - - [23/Mar/2015:19:13:42 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 206 174792 "http://redlug.com/pdf/che_sos.pdf" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
212.83.131.201 - - [23/Mar/2015:19:14:17 -0700] "GET /logs/access.log HTTP/1.1" 200 3794 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
188.165.15.10 - - [23/Mar/2015:19:15:18 -0700] "GET /images/2203e.jpg HTTP/1.1" 200 34981 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
31.184.238.152 - - [23/Mar/2015:19:18:57 -0700] "GET /logs/access.log HTTP/1.1" 200 29921 "http://buyraloxifene.soup.io" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:19:19:44 -0700] "GET /logs/access.log HTTP/1.1" 200 30160 "http://paxil-cr-25mg-buy-cheap.soup.io" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
188.165.15.10 - - [23/Mar/2015:19:27:22 -0700] "GET /paper2004JD/0407Dessian.htm HTTP/1.1" 200 2381 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
31.184.238.152 - - [23/Mar/2015:19:29:31 -0700] "GET /logs/access.log HTTP/1.1" 200 30595 "http://buydoxazosinmesylateonline.snack.ws" "Opera/9.80 (Windows NT 6.1; Win64; x64) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [23/Mar/2015:19:30:12 -0700] "GET /logs/access.log HTTP/1.1" 200 30815 "http://gravatar.com/dwelisatatkaagluc" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.13014 YaBrowser/13.12.1599.13014 Safari/537.36"
204.12.216.18 - - [23/Mar/2015:19:31:13 -0700] "GET /Archive/199202AntiSect.htm HTTP/1.1" 200 25462 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727 ; .NET CLR 4.0.30319)"
141.101.31.80 - - [23/Mar/2015:19:32:08 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"
141.101.31.80 - - [23/Mar/2015:19:32:09 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; Edition Yx) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [23/Mar/2015:19:32:09 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; Edition Yx) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [23/Mar/2015:19:32:10 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [23/Mar/2015:19:32:10 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [23/Mar/2015:19:32:10 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0"
141.101.31.80 - - [23/Mar/2015:19:32:11 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0"
188.165.15.10 - - [23/Mar/2015:19:32:19 -0700] "GET /logs/access_150302.log HTTP/1.1" 200 119881 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
208.67.16.11 - - [23/Mar/2015:19:36:52 -0700] "GET / HTTP/1.1" 200 9589 "-" "Mozilla/5.0 (Windows NT 5.1; rv:32.0) Gecko/20100101 Firefox/32.0"
31.184.238.152 - - [23/Mar/2015:19:40:18 -0700] "GET /logs/access.log HTTP/1.1" 200 33242 "http://3raamoxicillin.aircus.com" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:19:41:04 -0700] "GET /logs/access.log HTTP/1.1" 200 33485 "http://buy-dipyridamole-cheap.snack.ws" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
62.210.205.155 - - [23/Mar/2015:19:49:51 -0700] "GET /logs/access_130820.log HTTP/1.1" 404 88 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
62.210.205.155 - - [23/Mar/2015:19:49:51 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:19:51:00 -0700] "GET /logs/access.log HTTP/1.1" 200 34185 "http://orderrebetolonlineforsale.soup.io" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
178.62.96.206 - - [23/Mar/2015:19:51:35 -0700] "GET /Assorted/NUM.htm HTTP/1.1" 200 6206 "-" "-"
31.184.238.152 - - [23/Mar/2015:19:51:47 -0700] "GET /logs/access.log HTTP/1.1" 200 34553 "http://buycleocin150mgonline.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0"
141.101.31.80 - - [23/Mar/2015:19:59:59 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:20:00:00 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.39 Version/11.00"
141.101.31.80 - - [23/Mar/2015:20:00:01 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; WOW64; U; Edition Next; Edition Yx; ru) Presto/2.11.310 Version/12.50"
141.101.31.80 - - [23/Mar/2015:20:00:01 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.1; WOW64; U; Edition Next; Edition Yx; ru) Presto/2.11.310 Version/12.50"
141.101.31.80 - - [23/Mar/2015:20:00:01 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/20100101 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:20:00:02 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/20100101 Firefox/17.0"
31.184.238.152 - - [23/Mar/2015:20:01:15 -0700] "GET /logs/access.log HTTP/1.1" 200 36041 "http://buynorethindroneacetateonlineforsale.soup.io" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:20:01:59 -0700] "GET /logs/access.log HTTP/1.1" 200 36310 "http://buy-ursodiol-safely.soup.io" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16"
188.165.15.10 - - [23/Mar/2015:20:02:50 -0700] "GET /Election07/?M=A HTTP/1.1" 200 562 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
157.55.39.217 - - [23/Mar/2015:20:09:35 -0700] "GET /Assorted/NUMtime.htm HTTP/1.1" 200 2128 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
46.147.146.177 - - [23/Mar/2015:20:09:51 -0700] "GET / HTTP/1.1" 200 9589 "http://msk9927.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.5.0; .NET CLR 1.0.3705)"
31.184.238.152 - - [23/Mar/2015:20:12:50 -0700] "GET /logs/access.log HTTP/1.1" 200 37087 "http://www.theknot.com/wedding/salmeterol-and-shipping" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
104.168.43.19 - - [23/Mar/2015:20:14:34 -0700] "GET /logs/access.log HTTP/1.1" 200 4637 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
144.76.15.235 - - [23/Mar/2015:20:21:56 -0700] "GET / HTTP/1.1" 200 1273 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:21:57 -0700] "GET /robots.txt HTTP/1.1" 200 53 "-" "-"
144.76.15.235 - - [23/Mar/2015:20:21:58 -0700] "GET /?C=N HTTP/1.1" 200 1273 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:21:58 -0700] "GET /?C=M HTTP/1.1" 200 1269 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:21:59 -0700] "GET /?C=S HTTP/1.1" 200 1229 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:00 -0700] "GET /?C=D HTTP/1.1" 200 1273 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:00 -0700] "GET /Archive/ HTTP/1.1" 200 1796 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:01 -0700] "GET /Assorted/ HTTP/1.1" 200 1199 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:01 -0700] "GET /Bins/ HTTP/1.1" 200 488 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:02 -0700] "GET /Documents/ HTTP/1.1" 200 1189 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:02 -0700] "GET /Election/ HTTP/1.1" 200 935 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:02 -0700] "GET /Election07/ HTTP/1.1" 200 562 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:03 -0700] "GET /Index.html HTTP/1.1" 200 490 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:03 -0700] "GET /IntLeftNews/ HTTP/1.1" 200 453 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:04 -0700] "GET /LabHist/ HTTP/1.1" 200 1308 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:04 -0700] "GET /Leaflets/ HTTP/1.1" 200 455 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:05 -0700] "GET /NHS/ HTTP/1.1" 200 450 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:05 -0700] "GET /PaperArchive.htm HTTP/1.1" 200 4083 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:06 -0700] "GET /Publications/ HTTP/1.1" 200 645 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:06 -0700] "GET /Quotes.htm HTTP/1.1" 200 2816 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:07 -0700] "GET /Recent.htm HTTP/1.1" 200 3124 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:07 -0700] "GET /Reps.htm HTTP/1.1" 200 1734 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:08 -0700] "GET /SSUAS.htm HTTP/1.1" 200 1284 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:08 -0700] "GET /SYsup0702.htm HTTP/1.1" 200 47295 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:09 -0700] "GET /Scandals.htm HTTP/1.1" 200 12812 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:09 -0700] "GET /SocYouth/ HTTP/1.1" 200 474 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:10 -0700] "GET /Socialist.htm HTTP/1.1" 200 1050 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:10 -0700] "GET /Socialist/ HTTP/1.1" 200 2930 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:11 -0700] "GET /Struggle-Archive.htm HTTP/1.1" 200 2287 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:11 -0700] "GET /Struggle-FBU.htm HTTP/1.1" 200 4587 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:12 -0700] "GET /Struggle.htm HTTP/1.1" 200 14007 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:12 -0700] "GET /Thumbnails/ HTTP/1.1" 200 398 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:13 -0700] "GET /War/ HTTP/1.1" 200 733 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:13 -0700] "GET /Wardoc/ HTTP/1.1" 200 678 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:14 -0700] "GET /Women/ HTTP/1.1" 200 563 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:14 -0700] "GET /YaW/ HTTP/1.1" 200 757 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:15 -0700] "GET /YaWPR0503.htm HTTP/1.1" 200 4103 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:15 -0700] "GET /YouthArchive.htm HTTP/1.1" 200 5612 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:15 -0700] "GET /broadleft/ HTTP/1.1" 200 232 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:16 -0700] "GET /cwi/ HTTP/1.1" 200 1671 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:16 -0700] "GET /images/ HTTP/1.1" 200 1939 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:16 -0700] "GET /logs/ HTTP/1.1" 200 3273 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:17 -0700] "GET /oldIndex.html HTTP/1.1" 200 2380 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:18 -0700] "GET /old_socialistview.htm HTTP/1.1" 200 4622 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:18 -0700] "GET /oldelectionnews.htm HTTP/1.1" 200 2020 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:19 -0700] "GET /paper2003/ HTTP/1.1" 200 1194 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:19 -0700] "GET /paper2004/ HTTP/1.1" 200 1857 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:20 -0700] "GET /paper2004JD/ HTTP/1.1" 200 1334 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:20 -0700] "GET /paperarticles/ HTTP/1.1" 200 1735 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:21 -0700] "GET /pdf/ HTTP/1.1" 200 694 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:21 -0700] "GET /posters.htm HTTP/1.1" 200 1034 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:21 -0700] "GET /publications.htm HTTP/1.1" 200 5642 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:22 -0700] "GET /sitemap/ HTTP/1.1" 200 544 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:23 -0700] "GET /socialistview.htm HTTP/1.1" 200 4651 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:22 -0700] "GET /socialistPartyArchive/ HTTP/1.1" 200 3042 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:23 -0700] "GET /socview/ HTTP/1.1" 200 1519 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:23 -0700] "GET /stand.htm HTTP/1.1" 200 3709 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:24 -0700] "GET /temp/ HTTP/1.1" 200 748 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:24 -0700] "GET /tmp/ HTTP/1.1" 200 309 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:25 -0700] "GET /tu/ HTTP/1.1" 200 580 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:26 -0700] "GET /youth.htm HTTP/1.1" 200 18293 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:26 -0700] "GET /voice.htm HTTP/1.1" 200 5142 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:27 -0700] "GET /?C=M HTTP/1.1" 200 1269 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:27 -0700] "GET /?C=N HTTP/1.1" 200 1273 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:28 -0700] "GET /?C=S HTTP/1.1" 200 1229 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:28 -0700] "GET /?C=D HTTP/1.1" 200 1273 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:29 -0700] "GET /Archive/?C=N HTTP/1.1" 200 1796 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:29 -0700] "GET /Archive/?C=M HTTP/1.1" 200 1855 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:30 -0700] "GET /Archive/?C=S HTTP/1.1" 200 1807 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:30 -0700] "GET /Archive/?C=D HTTP/1.1" 200 1796 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:30 -0700] "GET /Archive/1969Troops.htm HTTP/1.1" 200 16265 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:31 -0700] "GET /Archive/1970May.htm HTTP/1.1" 200 5241 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:32 -0700] "GET /Archive/1971Intern.htm HTTP/1.1" 200 4769 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:33 -0700] "GET /Archive/197201Unity.htm HTTP/1.1" 200 5844 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:33 -0700] "GET /Archive/1972MayAnswer.htm HTTP/1.1" 200 4039 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:33 -0700] "GET /Archive/1972Pira.htm HTTP/1.1" 200 3873 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:34 -0700] "GET /Archive/1972SeptProt.htm HTTP/1.1" 200 4852 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:34 -0700] "GET /Archive/1972Widgery.htm HTTP/1.1" 200 3672 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:35 -0700] "GET /Archive/1973NovCoalition.htm HTTP/1.1" 200 3250 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:36 -0700] "GET /Archive/197409Intern.htm HTTP/1.1" 200 6101 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:36 -0700] "GET /Archive/1974PTonIreland.htm HTTP/1.1" 200 10322 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:36 -0700] "GET /Archive/1974UWC.htm HTTP/1.1" 200 6787 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:37 -0700] "GET /Archive/1975CRM.htm HTTP/1.1" 200 4623 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:37 -0700] "GET /Archive/1975Ceasefire.htm HTTP/1.1" 200 5863 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:37 -0700] "GET /Archive/1975RepLaw.htm HTTP/1.1" 200 3754 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:38 -0700] "GET /Archive/1976OctDTC.htm HTTP/1.1" 200 2356 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:38 -0700] "GET /Archive/1976OctPP.htm HTTP/1.1" 200 13018 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:38 -0700] "GET /Archive/1976Ulsterbus.htm HTTP/1.1" 200 2969 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:39 -0700] "GET /Archive/1977PeacePEdit.htm HTTP/1.1" 200 3751 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:39 -0700] "GET /Archive/1977UUAC.htm HTTP/1.1" 200 3405 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:40 -0700] "GET /Archive/1979Bennett.htm HTTP/1.1" 200 4490 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:40 -0700] "GET /Archive/1979HB.htm HTTP/1.1" 200 4924 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:41 -0700] "GET /Archive/1979MAvIT.htm HTTP/1.1" 200 4087 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:41 -0700] "GET /Archive/1980HBlock.htm HTTP/1.1" 200 6671 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:41 -0700] "GET /Archive/1980MayHB.htm HTTP/1.1" 200 2193 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:42 -0700] "GET /Archive/1980State.htm HTTP/1.1" 200 4440 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:42 -0700] "GET /Archive/1981GESects.htm HTTP/1.1" 200 14706 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:43 -0700] "GET /Archive/1981HBJuly.htm HTTP/1.1" 200 3505 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:43 -0700] "GET /Archive/1982IyB.htm HTTP/1.1" 200 7589 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:43 -0700] "GET /Archive/1982McGill.htm HTTP/1.1" 200 3446 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:43 -0700] "GET /Archive/1982NHS.htm HTTP/1.1" 200 2150 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:44 -0700] "GET /Archive/1983DTCsgrass.htm HTTP/1.1" 200 2677 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:44 -0700] "GET /Archive/1983Guer.htm HTTP/1.1" 200 7750 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:45 -0700] "GET /Archive/1983MI5.htm HTTP/1.1" 200 2186 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:45 -0700] "GET /Archive/1984supergrass.htm HTTP/1.1" 200 1823 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:46 -0700] "GET /Archive/1983Tressell.htm HTTP/1.1" 200 3324 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:46 -0700] "GET /Archive/1985State.htm HTTP/1.1" 200 13464 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:47 -0700] "GET /Archive/1986AIA.htm HTTP/1.1" 200 15685 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:47 -0700] "GET /Archive/1986Sects.htm HTTP/1.1" 200 11844 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:48 -0700] "GET /Archive/1988CRM.htm HTTP/1.1" 200 8644 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:48 -0700] "GET /Archive/1988Impasse.htm HTTP/1.1" 200 14621 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:49 -0700] "GET /Archive/1988Shoot2Kill.htm HTTP/1.1" 200 3672 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:49 -0700] "GET /Archive/198904MU.htm HTTP/1.1" 200 2367 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:49 -0700] "GET /Archive/198911B6.htm HTTP/1.1" 200 3850 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:50 -0700] "GET /Archive/1989DecPira.htm HTTP/1.1" 200 5175 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:51 -0700] "GET /Archive/1989Mendes.htm HTTP/1.1" 200 2850 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:51 -0700] "GET /Archive/1989NipsaASConf.htm HTTP/1.1" 200 4469 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:52 -0700] "GET /Archive/198911Jail.htm HTTP/1.1" 200 3695 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:52 -0700] "GET /Archive/1989Nipsaconf2.htm HTTP/1.1" 200 2162 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:52 -0700] "GET /Archive/1989PBu.htm HTTP/1.1" 200 2767 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:53 -0700] "GET /Archive/1990Boyne.htm HTTP/1.1" 200 2681 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
31.184.238.152 - - [23/Mar/2015:20:22:53 -0700] "GET /logs/access.log HTTP/1.1" 200 60765 "http://orderticlopidineau.tumblr.com" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
144.76.15.235 - - [23/Mar/2015:20:22:53 -0700] "GET /Archive/1990Brooke.htm HTTP/1.1" 200 2089 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:53 -0700] "GET /Archive/1990OtBridge.htm HTTP/1.1" 200 2441 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:54 -0700] "GET /Archive/199202AntiSect.htm HTTP/1.1" 200 9027 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:55 -0700] "GET /Archive/1993AntiSect.htm HTTP/1.1" 200 4025 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:55 -0700] "GET /Archive/1993H-ATalks.htm HTTP/1.1" 200 9438 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:56 -0700] "GET /Archive/1993NQu.htm HTTP/1.1" 200 19175 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:22:56 -0700] "GET /Archive/199103B6.htm HTTP/1.1" 200 3322 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:03 -0700] "GET /Archive/1993fascists.htm HTTP/1.1" 200 2361 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:04 -0700] "GET /Archive/199401Film.htm HTTP/1.1" 200 3040 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:04 -0700] "GET /Archive/1994CF.htm HTTP/1.1" 200 12416 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:05 -0700] "GET /Archive/7406DLP.htm HTTP/1.1" 200 2518 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:05 -0700] "GET /Archive/7406Derry.htm HTTP/1.1" 200 3242 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:06 -0700] "GET /Archive/7406UWC.htm HTTP/1.1" 200 7482 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:06 -0700] "GET /Archive/74J-Aug.htm HTTP/1.1" 200 3935 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:07 -0700] "GET /Archive/77StoppageIntro.htm HTTP/1.1" 200 4730 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:08 -0700] "GET /Archive/BLFAC.htm HTTP/1.1" 200 4883 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:08 -0700] "GET /Archive/1993SeptPost.htm HTTP/1.1" 200 2775 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:09 -0700] "GET /Archive/1993SeptPost.htm HTTP/1.1" 200 2034 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:09 -0700] "GET /Archive/CommManReview.htm HTTP/1.1" 200 3279 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:09 -0700] "GET /Archive/Contentslist.htm HTTP/1.1" 200 10710 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:10 -0700] "GET /Archive/CorruptionReport.htm HTTP/1.1" 200 5977 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:10 -0700] "GET /Archive/DerryBS.htm HTTP/1.1" 200 2811 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:10 -0700] "GET /Archive/DerryBS1972.htm HTTP/1.1" 200 4458 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:11 -0700] "GET /Archive/NewArchive.htm HTTP/1.1" 200 1966 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:11 -0700] "GET /Archive/OrwellAF.htm HTTP/1.1" 200 2968 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:11 -0700] "GET /Archive/PBList.htm HTTP/1.1" 200 1357 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:12 -0700] "GET /Archive/Rambo.htm HTTP/1.1" 200 3818 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:12 -0700] "GET /Archive/SPArchives1969.htm HTTP/1.1" 200 1648 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:13 -0700] "GET /Archive/SPArchives1970-71.htm HTTP/1.1" 200 864 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:13 -0700] "GET /Archive/SPArchives1972-73.htm HTTP/1.1" 200 2259 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:14 -0700] "GET /Archive/SPArchives1974-75.htm HTTP/1.1" 200 1832 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:14 -0700] "GET /Archive/SPArchives1976-77.htm HTTP/1.1" 200 1606 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:14 -0700] "GET /Archive/SPArchives1978-9.htm HTTP/1.1" 200 2015 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:14 -0700] "GET /Archive/SPArchives1980-81.htm HTTP/1.1" 200 1432 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:15 -0700] "GET /Archive/SPArchives1982-83.htm HTTP/1.1" 200 1259 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:15 -0700] "GET /Archive/SPArchives1984-85.htm HTTP/1.1" 200 3440 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:16 -0700] "GET /Archive/SPArchives1986-87.htm HTTP/1.1" 200 1019 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:16 -0700] "GET /Archive/SPArchives1988-89.htm HTTP/1.1" 200 1928 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:16 -0700] "GET /Archive/SPArchives1990-91.htm HTTP/1.1" 200 1846 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:16 -0700] "GET /Archive/SPArchives1992-93.htm HTTP/1.1" 200 1880 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:17 -0700] "GET /Archive/SPArchives1994-95.htm HTTP/1.1" 200 1091 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:17 -0700] "GET /Archive/Stonewall.htm HTTP/1.1" 200 10794 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:17 -0700] "GET /Archive/UWC1974.htm HTTP/1.1" 200 4583 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:17 -0700] "GET /Archive/testcontents.htm HTTP/1.1" 200 13254 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:18 -0700] "GET /Archive/testcontents2.html HTTP/1.1" 200 1984 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:18 -0700] "GET /Archive/weeklyupdates.htm HTTP/1.1" 200 996 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:18 -0700] "GET /Assorted/?C=N HTTP/1.1" 200 1199 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:19 -0700] "GET /Assorted/?C=M HTTP/1.1" 200 1193 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:19 -0700] "GET /Assorted/?C=S HTTP/1.1" 200 1200 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:20 -0700] "GET /Assorted/?C=D HTTP/1.1" 200 1199 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:20 -0700] "GET /Assorted/2006Debate.htm HTTP/1.1" 200 1838 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:21 -0700] "GET /Assorted/26million.htm HTTP/1.1" 200 3059 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:21 -0700] "GET /Assorted/AirportHS.htm HTTP/1.1" 200 3373 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:22 -0700] "GET /Assorted/AlgiersReview.htm HTTP/1.1" 200 3513 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:22 -0700] "GET /Assorted/BNP.htm HTTP/1.1" 200 3797 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:23 -0700] "GET /Assorted/BSandsReview.htm HTTP/1.1" 200 4989 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:23 -0700] "GET /Assorted/BertiesMoney.htm HTTP/1.1" 200 4824 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:24 -0700] "GET /Assorted/BestObit.htm HTTP/1.1" 200 3854 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:26 -0700] "GET /Assorted/AirportAttack.htm HTTP/1.1" 200 5011 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:27 -0700] "GET /Assorted/BigMacsFilm.htm HTTP/1.1" 200 2574 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:27 -0700] "GET /Assorted/Brown2006Obit.htm HTTP/1.1" 200 3602 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:27 -0700] "GET /Assorted/CGwomen.htm HTTP/1.1" 200 2358 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:27 -0700] "GET /Assorted/ConstantGardener.htm HTTP/1.1" 200 3352 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:28 -0700] "GET /Assorted/Corruption.htm HTTP/1.1" 200 5106 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:28 -0700] "GET /Assorted/FFailsSocialism.htm HTTP/1.1" 200 5267 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:28 -0700] "GET /Assorted/FascistsOut1.htm HTTP/1.1" 200 1930 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:29 -0700] "GET /Assorted/FemaleScience.htm HTTP/1.1" 200 5683 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:29 -0700] "GET /Assorted/GMO.htm HTTP/1.1" 200 4112 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:29 -0700] "GET /Assorted/AirportAttack.htm HTTP/1.1" 200 5754 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:31 -0700] "GET /Assorted/Gama.htm HTTP/1.1" 200 1959 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:31 -0700] "GET /Assorted/Gama050414Dail.htm HTTP/1.1" 200 1578 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:31 -0700] "GET /Assorted/Gama050415.htm HTTP/1.1" 200 2056 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:31 -0700] "GET /Assorted/GoodNightReview.htm HTTP/1.1" 200 2563 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:32 -0700] "GET /Assorted/HipHop.htm HTTP/1.1" 200 7465 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:32 -0700] "GET /Assorted/JH-Bushvisit.htm HTTP/1.1" 200 4146 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:32 -0700] "GET /Assorted/JHProfile0506.htm HTTP/1.1" 200 6006 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:32 -0700] "GET /Assorted/JHSBPost.htm HTTP/1.1" 200 4887 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:33 -0700] "GET /Assorted/JHonNIr.htm HTTP/1.1" 200 1542 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:33 -0700] "GET /Assorted/JHonRacism.htm HTTP/1.1" 200 7415 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:33 -0700] "GET /Assorted/JHonResult.htm HTTP/1.1" 200 2133 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:34 -0700] "GET /Assorted/JLondon.htm HTTP/1.1" 200 10135 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
144.76.15.235 - - [23/Mar/2015:20:23:34 -0700] "GET /Assorted/July05IRA.htm HTTP/1.1" 200 2297 "-" "Mozilla/5.0 (compatible; MegaIndex.ru/2.0; +https://www.megaindex.ru/?tab=linkAnalyze)"
31.184.238.152 - - [23/Mar/2015:20:23:36 -0700] "GET /logs/access.log HTTP/1.1" 200 77765 "http://buy-warfarin-lowprice.over-blog.com" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
180.76.5.95 - - [23/Mar/2015:20:23:47 -0700] "GET /Archive/1993H-ATalks.htm HTTP/1.1" 200 3885 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
141.101.31.80 - - [23/Mar/2015:20:27:27 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0"
141.101.31.80 - - [23/Mar/2015:20:27:28 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
141.101.31.80 - - [23/Mar/2015:20:27:28 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
141.101.31.80 - - [23/Mar/2015:20:27:29 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 5.1; U; Edition Yx; ru) Presto/2.10.289 Version/12.02"
141.101.31.80 - - [23/Mar/2015:20:27:29 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 5.1; U; Edition Yx; ru) Presto/2.10.289 Version/12.02"
141.101.31.80 - - [23/Mar/2015:20:27:29 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"
141.101.31.80 - - [23/Mar/2015:20:27:30 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"
31.184.238.152 - - [23/Mar/2015:20:33:25 -0700] "GET /logs/access.log HTTP/1.1" 200 79709 "http://spironolactone-100mg-buy-cheap.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:20:34:12 -0700] "GET /logs/access.log HTTP/1.1" 200 79965 "http://thorazine-buy-online.soup.io" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
31.184.238.152 - - [23/Mar/2015:20:44:06 -0700] "GET /logs/access.log HTTP/1.1" 200 80228 "http://valtrex-order-without-prescription.soup.io" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [23/Mar/2015:20:44:50 -0700] "GET /logs/access.log HTTP/1.1" 200 80458 "http://order-mebendazole-100mg-cheap.snack.ws" "Opera/9.80 (Windows NT 6.1; Win64; x64) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [23/Mar/2015:20:54:47 -0700] "GET /logs/access.log HTTP/1.1" 200 80681 "http://www.theknot.com/wedding/ordering-dydrogesterone" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [23/Mar/2015:20:55:26 -0700] "GET /logs/access.log HTTP/1.1" 200 80901 "http://order-alendronate-35mg-no-rx.page.tl" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
157.55.39.217 - - [23/Mar/2015:20:55:36 -0700] "GET /War/LetterHome.htm HTTP/1.1" 200 2637 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
141.101.31.80 - - [23/Mar/2015:20:56:28 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [23/Mar/2015:20:56:28 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.96 Safari/537.4"
141.101.31.80 - - [23/Mar/2015:20:56:29 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.96 Safari/537.4"
141.101.31.80 - - [23/Mar/2015:20:56:29 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [23/Mar/2015:20:56:30 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [23/Mar/2015:20:56:30 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"
141.101.31.80 - - [23/Mar/2015:20:56:30 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq100.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"
202.46.48.97 - - [23/Mar/2015:21:02:26 -0700] "GET /sitemap/0403App.htm HTTP/1.1" 404 88 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:21:05:25 -0700] "GET /logs/access.log HTTP/1.1" 200 83175 "http://buyvaltrex500mgonlineswitzerland.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:21:06:10 -0700] "GET /logs/access.log HTTP/1.1" 200 83462 "http://gravatar.com/orderlevothroid50mg247" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36"
199.189.84.217 - - [23/Mar/2015:21:11:28 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
31.184.238.152 - - [23/Mar/2015:21:16:01 -0700] "GET /logs/access.log HTTP/1.1" 200 83888 "http://www.theknot.com/wedding/endep-and-special" "Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0"
31.184.238.152 - - [23/Mar/2015:21:16:43 -0700] "GET /logs/access.log HTTP/1.1" 200 84110 "http://glucophage-xr-1000mg-order-without-rx.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 OPR/19.0.1326.63"
141.101.31.80 - - [23/Mar/2015:21:24:09 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.1.1084.5409 Chrome/19.1.1084.5409 Safari/536.5"
141.101.31.80 - - [23/Mar/2015:21:24:09 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"
141.101.31.80 - - [23/Mar/2015:21:24:09 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"
141.101.31.80 - - [23/Mar/2015:21:24:10 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 5.1; rv:7.0) Gecko/20100101 Firefox/7.0"
141.101.31.80 - - [23/Mar/2015:21:24:10 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 5.1; rv:7.0) Gecko/20100101 Firefox/7.0"
141.101.31.80 - - [23/Mar/2015:21:24:11 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"
141.101.31.80 - - [23/Mar/2015:21:24:11 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"
31.184.238.152 - - [23/Mar/2015:21:26:34 -0700] "GET /logs/access.log HTTP/1.1" 200 85958 "http://buyflagylonline.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:21:27:19 -0700] "GET /logs/access.log HTTP/1.1" 200 86206 "http://buy-drospirenone-3mg-online.aircus.com" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.13014 YaBrowser/13.12.1599.13014 Safari/537.36"
162.244.15.179 - - [23/Mar/2015:21:30:31 -0700] "GET /logs/access.log HTTP/1.1" 200 8741 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
77.75.73.17 - - [23/Mar/2015:21:31:05 -0700] "GET /robots.txt HTTP/1.1" 200 535 "-" "Mozilla/5.0 (compatible; SeznamBot/3.2; +http://fulltext.sblog.cz/)"
77.75.73.17 - - [23/Mar/2015:21:31:06 -0700] "GET /Archive/1994CF.htm HTTP/1.1" 200 12416 "-" "Mozilla/5.0 (compatible; SeznamBot/3.2; +http://fulltext.sblog.cz/)"
37.59.30.209 - - [23/Mar/2015:21:34:32 -0700] "GET /logs/access.log HTTP/1.1" 200 8849 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
157.55.39.135 - - [23/Mar/2015:21:35:05 -0700] "GET /Bins/ITimes031020.htm HTTP/1.1" 200 3196 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
31.184.238.152 - - [23/Mar/2015:21:37:11 -0700] "GET /logs/access.log HTTP/1.1" 200 87510 "http://buyvenlafaxineonlinelowprice.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36 OPR/20.0.1387.64"
31.184.238.152 - - [23/Mar/2015:21:38:00 -0700] "GET /logs/access.log HTTP/1.1" 200 87789 "http://ordercefdinironlinewithoutprescript.snack.ws" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16"
77.75.73.17 - - [23/Mar/2015:21:41:26 -0700] "GET /Archive/1974UWC.htm HTTP/1.1" 200 7415 "-" "Mozilla/5.0 (compatible; SeznamBot/3.2; +http://fulltext.sblog.cz/)"
178.137.19.232 - - [23/Mar/2015:21:43:27 -0700] "GET /cwi/Bush2.htm HTTP/1.1" 200 68762 "http://redlug.com/cwi/Bush2.htm" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
188.165.15.10 - - [23/Mar/2015:21:44:20 -0700] "GET /Socialist/0511Kashmir.htm HTTP/1.1" 200 2669 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
103.27.24.113 - - [23/Mar/2015:21:47:29 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:21:47:47 -0700] "GET /logs/access.log HTTP/1.1" 200 88800 "http://buy-propranolol-10-mg-online-au.page.tl" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [23/Mar/2015:21:48:32 -0700] "GET /logs/access.log HTTP/1.1" 200 89027 "http://gravatar.com/postmiclamarsiobrab" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
192.99.221.220 - - [23/Mar/2015:21:51:54 -0700] "GET /logs/access.log HTTP/1.1" 200 9848 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
141.101.31.80 - - [23/Mar/2015:21:52:05 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:21:52:06 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11"
141.101.31.80 - - [23/Mar/2015:21:52:06 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11"
141.101.31.80 - - [23/Mar/2015:21:52:07 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0"
141.101.31.80 - - [23/Mar/2015:21:52:07 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0"
141.101.31.80 - - [23/Mar/2015:21:52:07 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.1.1084.5409 Chrome/19.1.1084.5409 Safari/536.5"
141.101.31.80 - - [23/Mar/2015:21:52:08 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.1.1084.5409 Chrome/19.1.1084.5409 Safari/536.5"
157.55.39.217 - - [23/Mar/2015:21:52:58 -0700] "GET /paperarticles/nov01-woa.htm HTTP/1.1" 200 4094 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
104.168.48.83 - - [23/Mar/2015:21:54:03 -0700] "GET /logs/access.log HTTP/1.1" 200 9343 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:21:59:15 -0700] "GET /logs/access.log HTTP/1.1" 200 91574 "http://ordercitalopramlowprice.snack.ws" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
157.55.39.237 - - [23/Mar/2015:22:00:10 -0700] "GET /Documents/JH-Dail.htm HTTP/1.1" 200 3938 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
216.244.83.168 - - [23/Mar/2015:22:00:34 -0700] "GET / HTTP/1.1" 200 1273 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:34 -0700] "GET /?C=N;O=D HTTP/1.1" 200 1274 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:35 -0700] "GET /?C=M;O=A HTTP/1.1" 200 1269 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:35 -0700] "GET /?C=S;O=A HTTP/1.1" 200 1229 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:35 -0700] "GET /?C=D;O=A HTTP/1.1" 200 1273 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:35 -0700] "GET /Archive/ HTTP/1.1" 200 1796 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:35 -0700] "GET /Assorted/ HTTP/1.1" 200 1199 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:36 -0700] "GET /Bins/ HTTP/1.1" 200 488 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:36 -0700] "GET /Documents/ HTTP/1.1" 200 1189 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:36 -0700] "GET /Election/ HTTP/1.1" 200 935 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:36 -0700] "GET /Election07/ HTTP/1.1" 200 562 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:36 -0700] "GET /Index.html HTTP/1.1" 200 490 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /IntLeftNews/ HTTP/1.1" 200 453 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /LabHist/ HTTP/1.1" 200 1308 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /Leaflets/ HTTP/1.1" 200 455 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /NHS/ HTTP/1.1" 200 450 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /PaperArchive.htm HTTP/1.1" 200 3349 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /Publications/ HTTP/1.1" 200 645 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:37 -0700] "GET /Quotes.htm HTTP/1.1" 200 2816 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:38 -0700] "GET /Recent.htm HTTP/1.1" 200 3124 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:38 -0700] "GET /Reps.htm HTTP/1.1" 200 1734 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:38 -0700] "GET /SSUAS.htm HTTP/1.1" 200 1284 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:38 -0700] "GET /SYsup0702.htm HTTP/1.1" 200 15136 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:38 -0700] "GET /Scandals.htm HTTP/1.1" 200 12812 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:39 -0700] "GET /SocYouth/ HTTP/1.1" 200 474 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:39 -0700] "GET /Socialist.htm HTTP/1.1" 200 1050 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:39 -0700] "GET /Socialist/ HTTP/1.1" 200 2930 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:39 -0700] "GET /Struggle-Archive.htm HTTP/1.1" 200 2288 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:39 -0700] "GET /Struggle-FBU.htm HTTP/1.1" 200 4588 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:39 -0700] "GET /Struggle.htm HTTP/1.1" 200 14631 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:40 -0700] "GET /Thumbnails/ HTTP/1.1" 200 398 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:40 -0700] "GET /War/ HTTP/1.1" 200 733 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:40 -0700] "GET /Wardoc/ HTTP/1.1" 200 678 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:41 -0700] "GET /Women/ HTTP/1.1" 200 563 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:41 -0700] "GET /YaW/ HTTP/1.1" 200 757 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:41 -0700] "GET /YaWPR0503.htm HTTP/1.1" 200 3372 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:41 -0700] "GET /YouthArchive.htm HTTP/1.1" 200 5611 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:41 -0700] "GET /broadleft/ HTTP/1.1" 200 232 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:41 -0700] "GET /cwi/ HTTP/1.1" 200 1671 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:42 -0700] "GET /images/ HTTP/1.1" 200 1939 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:42 -0700] "GET /logs/ HTTP/1.1" 200 3272 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:42 -0700] "GET /oldIndex.html HTTP/1.1" 200 2379 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:43 -0700] "GET /old_socialistview.htm HTTP/1.1" 200 4516 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:43 -0700] "GET /oldelectionnews.htm HTTP/1.1" 200 2019 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:43 -0700] "GET /paper2003/ HTTP/1.1" 200 1194 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:43 -0700] "GET /paper2004/ HTTP/1.1" 200 1857 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:43 -0700] "GET /paper2004JD/ HTTP/1.1" 200 1334 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:44 -0700] "GET /paperarticles/ HTTP/1.1" 200 1735 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:44 -0700] "GET /pdf/ HTTP/1.1" 200 694 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:44 -0700] "GET /posters.htm HTTP/1.1" 200 1656 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:45 -0700] "GET /publications.htm HTTP/1.1" 200 5639 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:45 -0700] "GET /robots.txt HTTP/1.1" 200 53 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:45 -0700] "GET /sitemap.xml HTTP/1.1" 200 198 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:45 -0700] "GET /sitemap/ HTTP/1.1" 200 544 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:45 -0700] "GET /socialistPartyArchive/ HTTP/1.1" 200 3217 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:46 -0700] "GET /socialistview.htm HTTP/1.1" 200 4650 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:46 -0700] "GET /socview/ HTTP/1.1" 200 1519 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:46 -0700] "GET /stand.htm HTTP/1.1" 200 3709 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:46 -0700] "GET /temp/ HTTP/1.1" 200 748 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:46 -0700] "GET /tmp/ HTTP/1.1" 200 309 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:47 -0700] "GET /tu/ HTTP/1.1" 200 580 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:47 -0700] "GET /voice.htm HTTP/1.1" 200 4419 "-" "-"
216.244.83.168 - - [23/Mar/2015:22:00:47 -0700] "GET /youth.htm HTTP/1.1" 200 6786 "-" "-"
180.76.5.145 - - [23/Mar/2015:22:04:05 -0700] "GET /Archive/7406DLP.htm HTTP/1.1" 200 3148 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
37.130.227.133 - - [23/Mar/2015:22:04:30 -0700] "GET /logs/ HTTP/1.1" 200 37973 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; de) Opera 11.01"
37.130.227.133 - - [23/Mar/2015:22:04:32 -0700] "GET /logs/access_150324.log HTTP/1.1" 200 4361818 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; de) Opera 11.01"
31.184.238.152 - - [23/Mar/2015:22:09:34 -0700] "GET /logs/access.log HTTP/1.1" 200 99153 "http://ordertetracycline250mgcheap.snack.ws" "Opera/9.80 (Windows NT 6.1; Win64; x64) Presto/2.12.388 Version/12.16"
188.165.15.10 - - [23/Mar/2015:22:10:12 -0700] "GET /images/Nipsa04/?C=D;O=A HTTP/1.1" 200 471 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
31.184.238.152 - - [23/Mar/2015:22:10:21 -0700] "GET /logs/access.log HTTP/1.1" 200 99555 "http://orderaripiprazoleonlinecheap.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0"
68.190.29.39 - - [23/Mar/2015:22:10:51 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 200 207560 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.14 (KHTML, like Gecko) Version/6.0.1 Safari/536.26.14"
100.43.91.12 - - [23/Mar/2015:22:12:34 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
157.55.39.134 - - [23/Mar/2015:22:12:37 -0700] "GET /Socialist/06/0603Water.htm HTTP/1.1" 200 3381 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
157.55.39.134 - - [23/Mar/2015:22:12:37 -0700] "GET /pdf/SCWpamphlet.pdf HTTP/1.1" 200 376103 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 (compatible; bingbot/2.0; http://www.bing.com/bingbot.htm)"
68.190.29.39 - - [23/Mar/2015:22:17:24 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 200 207560 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.14 (KHTML, like Gecko) Version/6.0.1 Safari/536.26.14"
141.101.31.80 - - [23/Mar/2015:22:19:44 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"
141.101.31.80 - - [23/Mar/2015:22:19:45 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0"
141.101.31.80 - - [23/Mar/2015:22:19:45 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0"
141.101.31.80 - - [23/Mar/2015:22:19:46 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25"
141.101.31.80 - - [23/Mar/2015:22:19:46 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25"
141.101.31.80 - - [23/Mar/2015:22:19:46 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blondebitch.soup.io/" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)"
141.101.31.80 - - [23/Mar/2015:22:19:47 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)"
31.184.238.152 - - [23/Mar/2015:22:19:59 -0700] "GET /logs/access.log HTTP/1.1" 200 102435 "http://gravatar.com/orderuroxatral10mgfastshipping" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [23/Mar/2015:22:20:45 -0700] "GET /logs/access.log HTTP/1.1" 200 102652 "http://buytopiramateonlinecheap.snack.ws" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"
46.147.146.177 - - [23/Mar/2015:22:27:22 -0700] "GET / HTTP/1.1" 200 9589 "http://msk9017.apishops.ru/" "Opera/7.54 (Windows NT 5.1; U) [pl]"
46.147.146.177 - - [23/Mar/2015:22:27:23 -0700] "GET / HTTP/1.1" 200 9589 "http://msk9017.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1"
46.147.146.177 - - [23/Mar/2015:22:27:23 -0700] "GET / HTTP/1.1" 200 9589 "http://msk9017.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)"
46.147.146.177 - - [23/Mar/2015:22:27:24 -0700] "GET / HTTP/1.1" 200 9589 "http://msk9017.apishops.ru/" "Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)"
31.184.238.152 - - [23/Mar/2015:22:30:35 -0700] "GET /logs/access.log HTTP/1.1" 200 103562 "http://ordercefaclorfastshipping.snack.ws" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:22:31:19 -0700] "GET /logs/access.log HTTP/1.1" 200 103815 "http://buycabergolinequickshipping.snack.ws" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
157.55.39.217 - - [23/Mar/2015:22:31:49 -0700] "GET /Assorted/SSP2005.htm HTTP/1.1" 200 3702 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
31.184.238.152 - - [23/Mar/2015:22:41:20 -0700] "GET /logs/access.log HTTP/1.1" 200 104261 "http://buyacyclovir400mgonlinenorx.over-blog.com" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:22:42:07 -0700] "GET /logs/access.log HTTP/1.1" 200 104521 "http://buymetoclopramidequickdelivery.soup.io" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"
213.85.255.195 - - [23/Mar/2015:22:45:49 -0700] "GET /y?Z=qLDzmn02h0F4zM6H1g2+pdVyIWVCyge952wbHDdfpnT2sN1Z7+94GQYNYoO/7/hY5gFZ9vcFQPKdwNaCYWLkyn8XVgKtgPKRvXQ1zZBPoWNI17Qpdqh7a/x7qASY/mjoiGS8gZqeox0iEte1L0yif+ng59opuu24Ju1MNh1JBRhkufochxr0x/gYCo6JZeu1q2pt94WFQPWDgkJLAifViG4NtXX96e5Ro1Kou7/GsniSxMXxO0DFjl5v2w7n+ruQglpoOO1qk+jWm65sHcvoD5rWJ/1RgqI8eB7j8fUJubwJoIOExtrQX7ZWnsH/2HSongx5wvhdW829vTSqFgrIghzJ7nDz9LIgta09XwU2yT1QCmHLpMy5KvALY1keTo+gQcfGFNwn5tgs1MiYt72QDNIXaO8ic811R5moMbG2qgkk2rjDM6eiwZIgrElKAsRB/CqLwmQ5/IWSWvtZuN8lDSzyfOK15+9luPfLNSmBoKkpA2skaxpFfKuSrip73oojL46tWxRxPWkHxgL81XqexiblZ9IV+kPCVzntmDXILkv6/HzQvdzGn8x33af5CEtxOyUn2yneghCqHIRGYDZyLyclFo2bhZw7lGGru3qzmCe4xXDkEcZB/ntqHAEd6WBDJnrqP3dL4tB3SsU7KEvUbT11akwklQix4RruRHyzgysbfQS4geifRkEcZ4sokCG9a3nItj93cwuQMED8BtjDOCebAY0OB5XHWMk6w9pLUcR+b8LDtJBViw+mtMHcJyLDEZcFzvpmKzuQOsBZGLhwvinYfA9G7lJW0lXnR7zCMTZ5jvna/NzJQJR+HEWfGJGr92xdZ92 HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [23/Mar/2015:22:45:51 -0700] "GET /M?u=Iw1oSPOBRs1ITWMy62w1gYe+1kqyyJtIcAy6tuhm5P60SWkQ4wy++0+ZW9iNqlxAR/V3xyuMk132L7YlBWFHZhRiP1Ssz/04pVyuL40a8oi6FbFgKSJIl4HH5zBJqxnkze1IwFPumHj7jIGXj2xd/gqgxZ9dqHumDiQsC+FKhN/oRMRQE+Z9l5NMJT9ap78gEsstgBLDhbXy68TgBxiaONNAFBAc3JksH3OVFuAmZGzcLq8vPMDKqMJrv232zK/Y17LfTr1lRXf5Gk3rYCzCH7VoyiM1cwfCZ1/LPR6+XwNB61n5SoJ6YlATtRAyPItuW+k+ddG0UpGuQ5yNI4r5lxvXGZ02p94WOdmgm3DSuPWn7SyqSm7twfaJAuduuuTFAxEpPM9pdzcv/Z9Bf2tpw316Lp/3FwXpqoKPZ74UOYwRiYIOdUSe7mWMgZlRykRQ5OHBbg9wXa8Vs8prBA2WvmmfrFjGEZt HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
141.101.31.80 - - [23/Mar/2015:22:47:17 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:22:47:18 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.28) Gecko/20120306 Firefox/3.6.28 sputnik 2.5.2.8"
141.101.31.80 - - [23/Mar/2015:22:47:18 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.28) Gecko/20120306 Firefox/3.6.28 sputnik 2.5.2.8"
141.101.31.80 - - [23/Mar/2015:22:47:19 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:22:47:19 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Firefox/17.0"
141.101.31.80 - - [23/Mar/2015:22:47:20 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; MRA 6.0 (build 6001)) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [23/Mar/2015:22:47:20 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; MRA 6.0 (build 6001)) Presto/2.12.388 Version/12.11"
31.184.238.152 - - [23/Mar/2015:22:52:16 -0700] "GET /logs/access.log HTTP/1.1" 200 107901 "http://buycalcitriolonline.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:22:53:02 -0700] "GET /logs/access.log HTTP/1.1" 200 108155 "http://buypromethazineonlinewholesale.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
77.27.19.57 - - [23/Mar/2015:22:54:45 -0700] "GET /logs/access.log HTTP/1.1" 200 108411 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:2.0b8pre) Gecko/20101011 Firefox/4.0b8pre"
180.76.5.78 - - [23/Mar/2015:22:55:34 -0700] "GET /paper2004JD/?N=D HTTP/1.1" 200 1334 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
36.231.170.34 - - [23/Mar/2015:23:02:48 -0700] "GET /logs/access.log HTTP/1.1" 200 13115 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
157.55.39.237 - - [23/Mar/2015:23:02:54 -0700] "GET /paperarticles/sv0602sy.htm HTTP/1.1" 200 2305 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
31.184.238.152 - - [23/Mar/2015:23:03:24 -0700] "GET /logs/access.log HTTP/1.1" 200 109225 "http://www.theknot.com/wedding/acillin-and-without" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0"
31.184.238.152 - - [23/Mar/2015:23:04:10 -0700] "GET /logs/access.log HTTP/1.1" 200 109457 "http://x0luvox50mg.forumcircle.com" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 OPR/19.0.1326.63"
183.89.175.19 - - [23/Mar/2015:23:04:10 -0700] "GET /logs/access.log HTTP/1.1" 200 12589 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
72.81.177.197 - - [23/Mar/2015:23:06:15 -0700] "GET /socview/SV0302TroublesReview.htm HTTP/1.1" 200 3182 "https://www.google.com/" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4"
72.81.177.197 - - [23/Mar/2015:23:06:18 -0700] "GET /cwi.css HTTP/1.1" 404 89 "http://redlug.com/socview/SV0302TroublesReview.htm" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4"
31.184.238.152 - - [23/Mar/2015:23:14:24 -0700] "GET /logs/access.log HTTP/1.1" 200 110539 "http://buydoxazosinmesylate1mgonlinequickshipping.soup.io" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
141.101.31.80 - - [23/Mar/2015:23:15:08 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0"
141.101.31.80 - - [23/Mar/2015:23:15:08 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.91 Safari/537.11"
141.101.31.80 - - [23/Mar/2015:23:15:09 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.91 Safari/537.11"
141.101.31.80 - - [23/Mar/2015:23:15:09 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; MRA 6.0 (build 5970)) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [23/Mar/2015:23:15:10 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; MRA 6.0 (build 5970)) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [23/Mar/2015:23:15:10 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; Edition Yx) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [23/Mar/2015:23:15:10 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; Edition Yx) Presto/2.12.388 Version/12.11"
31.184.238.152 - - [23/Mar/2015:23:15:11 -0700] "GET /logs/access.log HTTP/1.1" 200 112378 "http://desloratadine5mgc1.forumcircle.com" "Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0"
31.184.238.152 - - [23/Mar/2015:23:25:16 -0700] "GET /logs/access.log HTTP/1.1" 200 112594 "http://orderclofazimineonline.over-blog.com" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:23:25:57 -0700] "GET /logs/access.log HTTP/1.1" 200 112848 "http://clomiphene-order-online.soup.io" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.15"
188.165.15.10 - - [23/Mar/2015:23:28:42 -0700] "GET /Documents/TDNPPt2.htm HTTP/1.1" 200 8913 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
122.252.228.137 - - [23/Mar/2015:23:34:14 -0700] "GET /logs/access.log HTTP/1.1" 200 12989 "https://www.google.co.in/" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
218.188.208.223 - - [23/Mar/2015:23:35:16 -0700] "GET /Documents/Ali.htm HTTP/1.1" 200 8450 "https://www.google.com.hk/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
218.188.208.223 - - [23/Mar/2015:23:35:17 -0700] "GET /cwi.css HTTP/1.1" 404 88 "http://redlug.com/Documents/Ali.htm" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
218.188.208.223 - - [23/Mar/2015:23:35:18 -0700] "GET /favicon.ico HTTP/1.1" 404 89 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
122.252.228.137 - - [23/Mar/2015:23:35:40 -0700] "GET / HTTP/1.1" 200 1273 "https://www.google.co.in/" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:23:36:05 -0700] "GET /logs/access.log HTTP/1.1" 200 114449 "http://www.theknot.com/wedding/hydroxyzine-and-delivery" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
193.226.34.229 - - [23/Mar/2015:23:36:32 -0700] "GET /logs/access.log HTTP/1.1" 200 13169 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
193.226.34.229 - - [23/Mar/2015:23:36:32 -0700] "GET /socview/SV0302TroublesReview.htm HTTP/1.1" 200 3184 "http://redlug.com/logs/access.log" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:23:36:52 -0700] "GET /logs/access.log HTTP/1.1" 200 115248 "http://orderacyclovironlinenoscript.soup.io" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
188.165.15.10 - - [23/Mar/2015:23:37:05 -0700] "GET /Archive/?C=D;O=A HTTP/1.1" 200 1796 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
193.226.34.226 - - [23/Mar/2015:23:41:21 -0700] "GET /logs/access.log HTTP/1.1" 200 13870 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
193.226.34.226 - - [23/Mar/2015:23:41:22 -0700] "GET /socview/SV0302TroublesReview.htm HTTP/1.1" 200 2434 "http://redlug.com/logs/access.log" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
141.101.31.80 - - [23/Mar/2015:23:42:41 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0"
141.101.31.80 - - [23/Mar/2015:23:42:41 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0"
141.101.31.80 - - [23/Mar/2015:23:42:42 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0"
141.101.31.80 - - [23/Mar/2015:23:42:42 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [23/Mar/2015:23:42:42 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [23/Mar/2015:23:42:43 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2"
141.101.31.80 - - [23/Mar/2015:23:42:43 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2"
177.55.254.194 - - [23/Mar/2015:23:46:22 -0700] "GET /logs/access.log HTTP/1.1" 200 13975 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
193.226.34.228 - - [23/Mar/2015:23:46:39 -0700] "GET /logs/access.log HTTP/1.1" 200 13384 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
193.226.34.228 - - [23/Mar/2015:23:46:40 -0700] "GET /socview/SV0302TroublesReview.htm HTTP/1.1" 200 2434 "http://redlug.com/logs/access.log" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:23:47:07 -0700] "GET /logs/access.log HTTP/1.1" 200 118421 "http://www.theknot.com/wedding/sale-and-glucovance" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [23/Mar/2015:23:47:51 -0700] "GET /logs/access.log HTTP/1.1" 200 118683 "http://www.theknot.com/wedding/maxalt-and-rx" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [23/Mar/2015:23:57:51 -0700] "GET /logs/access.log HTTP/1.1" 200 118902 "http://14ursodiol.forumcircle.com" "Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0"
196.46.125.2 - - [23/Mar/2015:23:59:11 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:12 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:13 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:13 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:14 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:15 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:15 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:16 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:16 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:17 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:18 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:18 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:19 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:20 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:20 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:21 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:22 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:22 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:23 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:24 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:24 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:25 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:26 -0700] "GET //components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:28 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:28 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:29 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:30 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:30 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:31 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:32 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:32 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:33 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:34 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:35 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:35 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:36 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:37 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:37 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:38 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:39 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:39 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:40 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:41 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:41 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:42 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
196.46.125.2 - - [23/Mar/2015:23:59:43 -0700] "GET /logs//components/com_jnews/includes/openflashchart/php-ofc-library/ofc_upload_image.php?name=magic.php.pHp HTTP/1.1" 404 73 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6"
157.55.39.83 - - [24/Mar/2015:00:02:33 -0700] "GET /robots.txt HTTP/1.1" 200 37 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
31.184.238.152 - - [24/Mar/2015:00:08:31 -0700] "GET /logs/access.log HTTP/1.1" 200 131954 "http://bmrocaltrol.forumcircle.com" "Opera/9.80 (Windows NT 6.1; Win64; x64) Presto/2.12.388 Version/12.16"
141.101.31.80 - - [24/Mar/2015:00:10:44 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Opera/9.80 (Windows NT 6.1; U; YB/3.5.1; ru) Presto/2.6.30 Version/10.63"
141.101.31.80 - - [24/Mar/2015:00:10:45 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Opera/9.80 (Windows NT 6.1; U; YB/3.5.1; ru) Presto/2.6.30 Version/10.63"
141.101.31.80 - - [24/Mar/2015:00:10:45 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19 CoolNovo/2.0.3.55"
141.101.31.80 - - [24/Mar/2015:00:10:46 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19 CoolNovo/2.0.3.55"
141.101.31.80 - - [24/Mar/2015:00:10:46 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Opera/9.80 (Windows NT 6.1; MRA 6.0 (build 5970)) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [24/Mar/2015:00:10:46 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Opera/9.80 (Windows NT 6.1; MRA 6.0 (build 5970)) Presto/2.12.388 Version/12.11"
192.3.34.98 - - [24/Mar/2015:00:16:15 -0700] "GET /logs/access_130709.log HTTP/1.1" 404 89 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
192.3.34.98 - - [24/Mar/2015:00:16:15 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
192.3.34.98 - - [24/Mar/2015:00:16:16 -0700] "GET /oldIndex.html HTTP/1.1" 200 2380 "http://redlug.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
213.87.123.62 - - [24/Mar/2015:00:16:31 -0700] "GET /logs/access.log HTTP/1.1" 200 14058 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
213.85.255.195 - - [24/Mar/2015:00:16:46 -0700] "GET /l?Y=ERK0k1yHExA4XCIOa0Q7tacyAJ6hyu/k6tLlG5AqhsV2TSm37XOMNOwZr24XR/O3yhJYkYAJ8Kq9EpIXz46M6aqYGx6o0ZPxCrfwfnE+5IoNYurhbvts9OPTWUZ70XntgHNJJnsQ8UV5B5VuTnvX4IJPm6RpjWAaMjiI84QD5dkCRycate7EtYoGbxNDce81mUWIYWTzQzHWZOcL1ODltRZxlx8fcweViq+hlr/qR7GEVmYRBZg/jYsdnAuCUWqNjw4CkeqALyimwrxBrK/J5xHfMXrBgG5M9myH71HU+d9A/ZS7E49dLa8DlyQ4uEezsgpwL4ry7/mNpCDtbpjFCPhtPGzfrW9nRasWTCdAspoHbw/4U8Wn+fkuBSxu7/MQg78JqqU1P9bs8bpNjkS2as6tOuqeU0H6EFoTumU57utSTDsCkb4NcDYpRz4T93yTyonsPYHyltoCQ2DeWjYCCwJK6IvF7gBg66ZOlUn4Kc5FwICGOwyPA7Qmk9WAaF81QLe+RC3piFX7HZ90lWaYoDeGk01ax5d+CXHrEj/u4c3hMMt/p4USQ4zg9cBaYp6ydS6k1GYhOi/RGVCYRWw7UdWM8uIdkNJN23EmWJiSWialg9REDRpXNbNBNSUhLdn08pEi7ojtAdK95HmvLrtwmbXZfmSe43hmFmYyGP+GJxpVBC2+uSIHsu2uZ5xZgiOXpuqTEHUJFuf72nue2Bpbxewn1h0f51yg8S4D8B0gm9apJ9A0RGzYeXcif2EyKqwrjQs2Dy4nbBjVC3xPQoUE+Z8kd28Satrmq4aj7UfCydavjxG6dYaVcY HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:48 -0700] "GET /u?c=109xBRd2gePrdYC+IS0aYqE7kWkryjvEBcyxkM41M2Fr2DvsRgVFDk0//ivekCX9cUj4PCd9PfFzgMFjBcSskwRiZLAd4CL5kK9AUDogNOtyrtENLTDnKBIurRs5x5qKVcYtoWHzQZ2ENMBi4Ep9sJOkTebScogRgDTqJ/4dw9BAmkuc25iJ49InDob53g2RdvsDTn9WFTYAk5FPy4JTtt260kHuP/nY+45IREHlqZtV79HtOdwAELwrF07z0sfkUnp4jo8QA+RWEvUVSUFy6qB3duRHisEmnE3nOqhmTSgx68cum2ZpP6ey11U+lpVwvaW5Hf5t2kinaoWFuYtF3uXl8DqnGditZ/NwKq4DQXuGvsm5mNN/jhZ7rvDrEZ7wvK89iDg6tJCdHZwrw/pb2Zmjsw++Nm/L0bEyxFWD0VAOUISvA768iJ9xNm/m/82/11KIIvzLzCb/Ye3y/xIYPyRcs+h62BleSkSfPmIeMDgOOAyl1aNH1226A3wtV9bPRg+saIr4Dvdq/dcbT2qH24MOOeVUFMgR2DDRirinS8x5ylZXvqBkSm2o7WsN4lDA720PFPc6Q2lJ9Q2+afB0xf1+WSgOlhLnnz32vYvqBfL78qpiocmZzLPIoLuQ3kB9AwdWX6UlWrQkJVD3oNLaHWwQlatw6SGZGVFRw9LeCLqiSlv/VCEhGz3qnIuy4vEcDFrNL62Y1Rcuu1PqRRRNNnuXUNwmzCUup+VgZPxrub5p7lDYvnlZSbZrGiLJ4LqrFdNOwhVo2HRQ7HbDFwaLHFuuafCblUNJ1DsCMZDNCulr1UJz2i/hgPnTaAP7Qy9b HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:50 -0700] "GET /y?h=lre9r0quWY1l+/eCR5IJtma2NnM7oGSspy7R8qYlysDygLbilClzB2hHg0TdOUTYGdv8FquY2TysZHQwhcblYhtjSo3P+WvIRy1RBsvUsJ1A6/CKKybYfOFmtTmqQGep2SuE+jqYXExAihP0hqnyphYnLvahZM7++VXm52bcbiklAlkofcQbniF88IgyyHx4sO6Gc7mOqHe78eeQX2QG18Et6uQQCNBxZBa5AxBcVaBGj40LnAV3ncjzyZyFVNJt2xtZewl8ZgvOkaktBKmFMY6xfF6R2ASzudF/1hzcSQRdoqN404rb3dcHmF8IB+ztHX9fQrcsXc2fh0Fr+cTazx1FBW6Syfasr1Lt3iu2vL1F4h6KM2Md7YdIbO58qf0QqWUmgTxGCU4CRDuRmmghmv5SPoXSUPnxUCeO/YVvJ7vrKniVEvfXlPiEKiiKtjPhhRetFwWGztRQXS/pzCHXRJQopyvGE46aXUdmVM9DPAhLzdtS5NwK0n0CFs/oI9aE5lysWLOq2Oc2k2YOYX0Tr34OAGNeCLQbLkjVCFJGLWnBPaQCvNozxdyTUPtFOo58GTcV19V6YaiuR61YlrX7UXtf71U7NGBchk23FTpYm3CC6us1+uPC1UUq64XMYDRygzHEzKYMmrYuCjdNgcwuyPoMQKx4Oc0Eigi2ZGZim6lCIJAsYl3/RSuCfYpBLVmwSr2eT9SZGfU7vV7MwHwN5vhn1FWKiQN5fVcMV/0q54UQkhhpDW0K+IG+3BnyKrU0+RPa2+fzG6kzX9udxD6Lm9ePm/OU39choScqivldO2y8ctf HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:52 -0700] "GET /e?U=uPHjIxC0X8r/lk2NCEn1IIZB2aoL/Av7jmK+H7yFPntHI7yu4m/reaGCelwMWDmMry43tYSzQE49v8w4ee5RbAGBz1yksOMhAe59yVxN5ojH/G0CBHvtaCCoWizohVAyl6b394JgWYJW0cLpHWmwO/gYdj2E+rqe+v7WaiJ9MCTgIlkthBiHdanPIbxFwDT5fcz3Hoqe+5FbEABhlz1ngm+AxhtMtFzI4Nm10Zb8ppb4MOfP/TdwIdvcvlGJQucZllf/oZJ12sEWXxwXOREpMzcqmz6pdcO07FInR0i6YLKfV4rME2briWrlvpfOIpeZFx/c7rtpkracL5BDeb30jsA4JZitams5ZrJjduGhRIDYRjG5XC0o9zLExfT1fUOMpElGSt6IH2d3+Pdd20WuqTFQXhMcGXZ14Eu4y+djDZyTSNBXmw0QD7si0uS4n2sTOrtxTCtImTFAaKhZm9BvkExIbz9iOkluLFujsXCDSh6mk56dfKkOHbOAUWUq7/REN7JKDdx93dR0sTocb9f9swKUUlDd6a4YtlpihdB7BlQyyksh3I/mooypnIlERS447W2PankjsJLmptGOxCr8cdsv0zq1C0bqMQFB0s4qHZ6AxnHYzD2hC+IX5SHpuLn1bikHxTZrCkSW9wcbeKdbkZbXqHb2Rv/HjG3ocnGaGOmUqpHulpxvbpZd4emSpa5VeTwEq2YGrPljR1fR66oUE/4AA9sS2N5VmeoUYuA6DxKcNkcQ3EmFaTwivwwjUpOH8grsp8hZGTpiqaIlEzb2WTDZDhh8bSEgQg74R HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:54 -0700] "GET /a?R=J2Z3UO55Yfzfnf5NDCMBTOIj5Tl8a/GTDwr7KzMxIZFyHAdalVCByhLPdF8e2knOXkUkxtuwd03kDeTqqxRjIEg8Mdx3emBxl9HA3mAStpuUkVprxqAQuMbMyjf2eQ2aXiZSj3pbiCbKJ8YAjxvt5OlsbWfKp27GamJ33TXE46eTeidb5QZkUdSfSpR2cjZfcTViy2OreiIX0yKamAt1mW54XYKl7O/mJWIBsJEiv8zAp5vgWkd+YgBZfRrfPQ7Ym9Y57CcXrm/ACxjNSWZmP5jI8pH9GsCPnmJtUvvBkbU+cDK87DQunm+whrjb71CuYNi/OkkwsaR3xe7n+5BAXfsUeWmyOI6k9t77st/9AW/ScV2THGN3PqvCemgiqwgXl+1i9Y2zMszK8m8/nO1dicv7t4wrSKuIC3taStm2FlHfhtigWYwp6I5UIQAud+OkvrHXG1XZ6b0fBldR0H4BVbbRP0uxvFc1vIiwyGFmyUxTOvEFPQXBiBZi4GRmTpzVZDLdeVkl7M9XDldpfOe168PxOypSh2xORrjCD6FVd2esUKWCzyLsLn03SDvelh6TZX0xTvFjiqMWnWPn4M5W0eNNHhz06V45DXGrR6hQvwE7AXSNw07+F2bDLsIJS8ZMiDzkzeWRi93L3gknZsY92AvrnDD52e7PmwKSGe8z8mwpTI5AAJahuANwjfT8DBUdr0Dw1ai+2e4c52D9tyfRXbEPNUVb8j+1QJTAHX5o7zQr2R7edpBlnikorKdagWzPJ16iG96Q8a8K5+0b5Tz6Ikt6pDWxvRZOfewYotxiNpGRwShlSKz+2U18wX4nUZVejSdnzszwOSfzStPoegkN HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:55 -0700] "GET /R?D=F0KdDUObaHt2N5TW+ACo44GEIdwFJsRadrzkXP/76VXxcKCTykJqjZEHHUy3x+aSxLAM8D8mUzkma7sy5VfrdwCBmQaO19QeddZu+fHm8BzF/jO+XOs0SRM4kawqbbTqfPtJgcouXEkSlhqiL+BMjQn4c+OWWhEa9zu8BzyLR/FSAp/rFJkdJzZOKet6uxwKzuTNs6tAkaKB4U0CE/eGHqzNV8jvzPa45LkpQPQ5IFol7f8CBvszVj/iKla2R/8l6xmggbh2ldJ2xMY7i94HclWo3X43kWnJ2LPuabJWBX+WQ5Uam5dLnYDnjlZ4SuaRbwJhvWEgSpxgqHnbO6pFDHy/W0Bju//TU+E3YYzOUUsT+pjGtCwH+4oMVnXKQcIhshmVjklvVdlgwfhPZwtTZrJD1YbZtJAn307iQ60cHXsFgxVSSrLlISP9sjyTaliv/gozDVRx8fiUguwqyLexPD+t94EaHpMAJCggN2hryiMJB0HzfbunFU3t/XwHefgRVHVErhMkWG08G/iPlLvph3zDDak3mw6qhr2DoAPdge01Hq/5uYM4DE5BadbTMKr7+P3AQRWsr4y4vYgvzfrt8tKzA8Mc58cJMq9xtU2L2dfe1/Pb+295NnedCOd7lBmdfh9m9gPEvx3jwaS2QA/gCEHHQz3fIPnxrLZqfjcJMcsXLrgGyeYNO07TANg2I5EXBRGVRCb0APjQJRemDeZdhz+U/9n0LZqlgdgdT9VxIJTYSl+hHz9F+cUccTC7shfDvqA3rXBgmFBV/GT7UOjZ/XoVvhNSMMi0k5c2esJFU7gUca+psX7my HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:56 -0700] "GET /R?K=/1sqcmUG6yqtOIwkZygClx9aQAIbDvDH+baxBG1PjVW7lzETkzeBEyXJBJRWA6aQye/74F2sgYdblFqDg/cImiPOboKOxziV34vmzmTbAgjuqYxiY+XhVJJAdXwEco9wRKwha93UpAleEDDYqx/ufXEhVsLltAd7SEaX6GVoNDjL64MhL88oKTV76tfEmtdtsjGhq+I6usPY0Xu4LWzUgLNDsivmD7UL6sm/yjQvidGOAcpy//GSdVvSZBlFrP9baFFKpwWRI2SEEkOqb1OHQcOfrStDwqLcvdNA1sReiDCIpsdRrxGah+kbyGdpIW50Fh8nS0TVAeja/CLaQOKz3ardemutWfOpVOWtJB17b2HrzyzfglN7vt6sM8BVtHozRzhZkcmgtQ1StOJBJhFySkpItsNJqJBeljU+UtB77GOKj3Lb0G8Yn0DfgnXpwxO2skRimTVeBEgClFGIewKJgZlyoWZvrbH+cSYdtK8sZxNdGJ7OoX0EqFS5p62fEzBznCB5LYoURbSabg/bb40TL26GG9mlX4N1u6KSImtGdC0ZOFQeufbQzoz2iCuvMg4VkpvkrsqhrddyBxGgJGJzXq0UElW6HgdrFFM3BZFFyzFcRJ6pr4XsJXMWH1ixb7YzxlmULMkTYCtqPloc3sh6R70ukTkAO1MBTsR+ukEN4glxWfklg+J0CBF45sF1YQvIjJH/mvLMPkKTqnmxRcwTp191Y42wyA2430lULXK3VhBaMaA7BvdlVlrndcpM0E/YGWNM2nSstpq5orlqxYs3o2Oo0zBjYIAIlGvR2G5G94J8zKp3cAIOp39s85aPCJIV/3+ZpRqaaJqdJWI5tqlX8iOkE HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:16:59 -0700] "GET /C?Y=nvF7XGzTwFatCZRakcw/CypRoyS8IElRvD59YabhsKFE4f47Z5S1AgvI0DyUoT7n2NyGGVyJA71ert+PeiqUI8KJ2+UFvnc1dMvYWHPSesiWaIJhPTBfSPbSUUcnRZwR8AgAME158889fFjf8hrZ1hwu/CNJ1xu4KWboWpKbCK+3s02aIea2iNEohHMs1rdc/J86L70Ja4xVREEIGKVcjMWdcZ5rEpD4IArHdXDo7pIJBphXyrX3R1QZC/MWlRd6ipaQT28ERZ3xm8dND4Ahi+e8uw6PdGRNDytp2rpYP4lLEEpPM5wb5N1T9awuTURDFtsaUS7LvDKFKgswUpmLieBY21+wIAx1FJ87iPjwRiqOW2DdazfmY+5sIULIUSAWKKir7JszHZxLHrF/Su+7YgQOVDAfg7Xj/RovET1FwP/EGkfMuTe6gb7lWoF3gPhf18+ELFR0eHUO57D7Bn7oFDZoNPUt0p5+2bFXZQtWCMv+ETouUS7CbL8QBOujpJ/VtUTuCE1SNrBaO3900cT6xQoD2mErMzxGo6jz2nXHojOZVqD2U6NR3wO4mX9GULAXq3NUt1zkWrsPm8rFuT+xL2Jhdmkxoacih6uLsnPFkHmWRrw+kIDvyDFNvoWMWdTQAr1bBz0jYxB41U/nbUiDzdEbteoWQ4XKgSESjwtOf0pjTGrvxyeqBBD37LXpJmEyGcaMESKpnlQqQM2vqGgIXv8Le8BOOVlKLV7nW/ThqO9GrKMvafUhSJg0ruB1lgczkmBo/m9uTkzBd211NYjnEZ+ePAEpZR66 HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:01 -0700] "GET /I?x=zuJIuQMnFUu9im9T0dJHyCNWN9IZeGIzlYM9DWvxa27ktCXUghw7ftE60vr0H9OyfPqFvPTROspvypZNpXwCSLz15OCu1ZbeQA7XILMm3dLn8awsWqSdmL32AZFUHykUKmxxN4l5+Dc0+VR69MjRPjn37DrfMGdYiUbz59OgenXFaqq0Z/lB3hJjCN9VLQ2W6ppJvMuQN3u+VFOFNpPPSz0zioEMBWbMfFwVdo0vRRatKNK0OKhW8PWdqGm9EI1KK+wcm3+XPaPClB5v4TP5oWK04Fv2EeSmBqUUtRFshhe7zLbIVhNVyNdkWC9X0l4GhcH017Kd2CZaV8AOmXchXcSloVMd93ub1JZ6gF5SqHQwpH3pfzhdWpZ/Qilf+YQsgvm6cldRoMu9KQLIAE/SlFPs1tTQ+C4mp/6fDHeiidCSK4m/xfmQwshNtk0arjo5+mFzfnERUqjuTHhWu21WCDXdUXUazqkXbQco+lryYg6Ur5cjvg/4nXORnAeO2+W3mG15+3vcbREK0Uv2BLAMieSTsNgPgqBGep7LSec1N5Ftap8jqfe4u5vcAEihL1GfYBFvF/rROxTPcj18mYh8Ftluc+PDcVgbS17Zfx7lLiBnOA5Gw3/vEk6cbZ/9cv0hQsFxL8kYvvKjv3S3ZpYSSOzOUisPwChTTKjHex14IaYt1pEmSDWW0AXi0fbFQwRZQYJOOjP75jrq53ZwrbBnPILxF1vQYpykeHIDVMGHTV9z1Yf6Rm85mX9sdutjRNlROfbF5lVGid3RfowGvkbmLz8pRM/qKD1GfUdKFFD6fcUlH39asIavKhi3MYLCMxBUVHHjM4ICn2bcUZDnWV5qp HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:03 -0700] "GET /K?A=EfjTpJrw5vSEdbfXjQ6/VJCaMhyzGzP7IdGx30vp45ha9HNeXf8VsoM7IXGuYsRmxsEfy6J1jL/NeljnTwy4c19RxAyXMHQPpJpx7V6R51nnn0EELiqEwQjMXsF6GQXko8nPLI979J/h4nT7wu0Dm5gsFUJ+Mae4rIYRTAtszHPXOH7OqAmNilsYuZyqNd9fHynu0/DfWbu2g3iR8KEYx2z+3Cr0ARlHzsbw9Ioed+HyR7tofL2B0RCW5DqGfctq27RxZQYfAs/+i8/GsxJfh3wYsJwyj07ehXJ17O+XSZcJHJx2EHCtoCaRvy21WnbyL//ZKNtk950631x7oBpDeVrv8cAnX1756VetuMgnIY4pj3f1vCJlMon6mvcA15qbD7oXjV7V7AY6bBZDVkRZQ5SfL/7crIviC2KCXPNL7tdBUQkBcdSSc9vh1QVD/lzMNxY9kzWGLhbS3xfCQLnMoUIh712qBKpO1Fpb4ODlOfxbWlaIXmUvmf7PgUTPN5qF0iGCeIF4GYf/v7TePQhJcHyi/T2y9a04/ZueNMmMBPtWCZhthqOJVr7Sl27fDLvuUeDV93TvGGeDkOsq31Kt3yN9hzk3csNQOtwH2/HllaS0httCyXrLZWWYricJXjZY09IRNz9Q1CAH5b8xBnuMv2iyDEif8nO10KePwd2wOHc9zFCsqIwdANKjQoPYXCVOG5QvzMr2GiNRm1n6g+3xrRVCxNeQfkCFlQJeXLrKGhu6+1nUO4HEBjk1VVGD+cyzQAlotwHxjKdLOnSmpM3jnDb1KTYWGrT/rtpK7Hm/N0fmiL44xwgERwSgRdGFtE9jPTOyfvfHxVQNZneUMEobmWcr HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:04 -0700] "GET /v?n=LQLeG8TfUwjkZGXP/6hXwHYCiqAjBgUxsAIqftAqbgrDs+aYjiabH2i7FGG7lNC2CfAhszvN/yYkCIOPWLPwzPbFyRHjWIQedew5hUKxDA11rtLL+s/v8bqSQy73ogI2UiAxbmR9vEHE8dc0jXyimgZEmQEHoFFJOuyjkZ8ogDFoKzmCFrDEVo+/X5inhZB69Tj606wVTZnqbEoxja+sg/aw8iN84LX9FflqhE5FGryeXFt2BKwJxdJhZD9ps64hBbfHYtfrXTCXoucffo69bXoqGWCKJIR+uHGphK/snnAGf9608eQnaL2U6MrkfZKK3vvhiMXsRBYwu+wqAVSTrb4K9GDTyhOFKs738Mp8S2/UdJAkK+RdCmPazDJwhSJtdwLYK0Ox5bRa8kYZWGRbmsc2aMTzDEnG/y5G6i/r2TLWZyZdXYY2t1X0KxNjkSsFQMfAvubGbVhST4pw7RvkS9huK1oV4DClTL8oxJ1+/gFNxgMzjvTXJXwpsFozB9qA87Bne+iDVWJuZS3PIJYlX95kBCQ70FFHMqjiox8zjkv7Xs1SFUaSwYABsb+4bXDQ99krWMVTwdicR2ssNlXdgmU1A0p86sHreslhr7o4r25ttOpOrVn4uJhV38mMbBChMk0F59Kq34/77+hbPYAHNH94q22wgBwpHAnMNpzeYjVw7sYCLT+i5dNUuVnAyfj6zcYgeseY8wDa374etLnmUjRlygweGrbEFhFKsD/EboqldQs22RYti80aMxrEeO4JTE6kV2MUuPQybt2QY5QCqLK6qiZomrnZC1WnWD9wkxevNarGVZiSh+/Sl+d4t+UG3mKED/2RX8sd/ HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:07 -0700] "GET /g?e=ZS8Y8m87zNLEOsg3nJjUhBiJCcg7hk4WkcpRI7VBTTJh0ocU1af7gTq4y6rau9D7nFwsIR/wmPc9P3yyCCrDM8pddkpKrtyxYmirE7XOGWZilgoh4S0RzL7GqCH+oQFeiYiOa8o1vHK0yC7jXmLadCtKoe6rkki8BN3iy5m2POjCoEkrGBh2Wp8U2flz17XU3yoMaXhhNs4DV6sjyzz0gwftukNciZC0MeJ7EV/Tl7CuOxXZBKmSqZkNQG38Cu/2Hkp7+Q5FO/Dw+ORTUiwMZ95B3fzoYVwF8gBmepExkL4bEOqpKBzHsdsrTbA2te2HPKDNd8JitdIOFSuzJu+/i6SlfEGBWTGQ+Je+2ITipgDj1aCI6bbYVOq5RtlQBhbSV47R0vq4HvM+ITAXS70Pxgz60tYiepdMICRGsJC85bDnpff9EAzFE+ut1mnFE+VDkgW8s98TfYXYK+D9rELgJ30yBuLz4aClXqjiagbxSg5M01buU9oKbs4jR21rXduWWQ+ePtYPd3GFvw1yizLmesrFhajDY0PdwFUXtnZnF7MOaeH+6j1mTceIMz4sfyDOSBJ9UgOhREpPZeoUfzgdDN9E/Kt9sCHLjceZsoAPxh15vWfByLLEz7jR2/OsAMmkFUDGfJOKV/lyeML5QKpR1OChUIs9uECApqZ1hUeaNy3KKmXIFSi/CsZgla+wGL+SPJQ0KLfapu74Yggpz2KjV8Dx2ORXCkhvosXG9VLSPyN2f/J+PbxMV3LAy/hmtZB6FPZFfHfk9PciUiqQB8+5kfEtcEaZZZ2BFRpNUT HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:08 -0700] "GET /b?a=SOnCdD+TUm0eiiNz5tcJwlv4QC/5J+TyAmRaC2ItNQ6U1891vlS2aDiVtxWaw+FayBk7XSdP+lLaLErGaubyxsMj6cGdUtSDDmbSypm6pnEXper3l71LFBtO9Z9EA+rys7jDumi348b+gz/GMXESPq4ua9oije3lZMnvYZIbcazwXvnr4TSwMdseW+pCigGSmajlD7tq06kASBKfNf2T6Fe9P+H91xS3Ps7TVGlDSHZHYEfmRdSqrtVsmBksQoOpyodZbvqSv4e7Fm9aCmvURzEFKb5Md4WbgoRrG4uRmS+N3DxAIxPkWFgRaI2DJ647j8lU/728OTOfhGppldcwByqoPgnQy1sX5LKwkCwR5QdrWEcaxsJIiHT10H5PlbC0AQRuCIS2DpYp+cybR9KhLo/h0WhXOCjgWTPOgk0CYOo4t1mOFuFsp6NMFEpOr9WpZeSNDLDmiIzWwpGM2Op9lCYE6i86nhuxVrAaxz2tBtdzsiU+2Lm7tvqbPJEhHxou6yYOevQPzZSuWIodWNIsd6ozYhcqxX4AXtl1kEZbvQ7ECo5Mzlz/3dmskCTEsNbiZlEtYnyL7sMTBD3OwMF9UZNN+yCBC4oQK4TWGWVkGbgDNJaAbB2ezChREDb9UaaFisFmnq1ndFgI7OUvHq0UVnZ72ZhqBiTyhC83RGGAM+46Ea24AP4ktaE5odkHR1GGh/vKr03CTtrPvd+lYMy7RBC7apOU+qpERDjOQ/kMpUZjvGGBPUUpg6D/NQjGdsQ5DZUg1EuVdXXG1YH7lAINVKoz3S+up3O HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:10 -0700] "GET /B?v=odvPHPfL2rs0SLJnrft9HnkY2QCIohXnZ6QQYrTSI45WpxMCt6/xdaDaAAk192V+3Cexl1y7b7W/xKPt7TUUOmHbyvx7FgjN/mtUWRUFbUy4RBWAO4RuSloiwWtJWJVV3GOqemtk6sDWSe+YR+nHKwu4L/SCwPhWiR4/3mGSP3poGelN4ksNn+kSl+S+up+1pJqdAR2LkVr34UcuYaLaNeSEyZn1iei2FmzYjlWO2p7yZ6s0FGvhryunl4B/+lT9hid0fJoIxSSXzJ5V4wRrcny3tsDq47JVxV0m9aQOYd0QTdgyGiezRDxRBN+RWsVMKpFdJVryyO+RQVH352yCe+eRfZmY1McZp7Sev8E82GRGFFCPrhRtwk5WIC4FzGGn3pAUDRuU9+uWpMPR76Uh2mSmr2HHLyoGE0kzKLelGhtjEIKXIk2ces/8/afQRrNQAWDJKMD/y0VTLAxFofZuRHJpbvWvQTiUT3jPs83m/fzSyrTQv490M+LkWH8bje0DdqzQ1mnVk4feyNI5dmCwXSl033cqJAMU6Va66PBiMcMCFHD9qT8CGR+UjSqW5fMVyDe4sSUsOdgR/MgHhTPwLB+zHLCjrqg5UkCBFD+129hKgp/Rlq3M1Y6Sj+Vj1Q/yazgjgB00YS7pISQYCGgcdpX1JZK2I0V33DEA9/uLGgsE3NFGRjmAWUVP+kZPno8UbnWMcZKFIxgxrIZxF703MsN06tmjrc6Vi8DoK7uj9pUg8b83e3P8bK7hKPO26tPsphbLtAqQpGa3wVP4sUIiLWAPkz1znbWouTx1FfW0DWB+BC+WGc+HHlmE/i HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:12 -0700] "GET /E?t=K8WsyDTlk+0i7YSjKCTD90NwPeyCtnd9+fIIOuSe3TIZwK82AVUUwuwXdHaMvohQYMdxB+cxXa77NvhH6g2CzA6/F2/ReyBUUdv9u5fep3li5YbTy/72X/uEVFKDI5JgbJSJR2u9538e5PDoaoUjUxgPYEXPa04UrK5OmdpSZqQNPKLk2S5VfmYzTb2DNNzdnPZymmD8xaU0w0reO2Ckjtc++mcAZ0t/rFCB5mz0K90BH4vaSVOabMNCtuMzGJiPiyx7k9661S66L0LcSvq/3yxu6rhcmYW7j0+6F4rqZpeQXEvwuf4fQJy/6BoNAzX9t5sNIdP8cXBzRx8E2R2ntqDFS3T2wJUkTqNW/BiuvWvwtC3/Ydtt2vpBB24x+26J5rTRFLRDO0Fr5MYUqhn1J5C9GzRJjoL1PXxI3CibB7o3CIFCNFqRWM7tuT6+ncWqvQAKfDKpzPdz2MVGRBSvVvCkEPii2PAXtEZ4C1xV/JFVlf0YhG1EnsTL1GulMxiaQw/Ijz5h9DygbQEHEXhH++S13um/+XJXP1W0f6p2qlWcfygMqA2EwNjf6F3ULYT5EtsbR+0hZDJXyYisg3HVBQmvBKU95WO3Vc6r9ycT0X/FKpEvQuG8JCkXUl0lAUcZdMNvMiMbFGTK/1SZBrzrHm06JpwfiOJb0SN5gywgt4CDRho+Ori8af3+bai3GCfZJJ39w9T1/Oh+ALwP+7nBby6LUX8/SYu1tZiiy54zx6jYoK81DaPQBwza7prA/gF9+MpDNbIDik/tsuqEXBpeW3E/hVB9z7lEsIOo6Tf8 HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:14 -0700] "GET /h?j=mht1ZW/YqNzM0eHzuh1F7XYd+clSC0f8FNt3YzzHxOBwIOuVfLEAPLhyk+pFMa/Y78VyIrRnPTKTWvx73aoSfP8eveD4F7/On/yfJl0B+viLbUWXPDPQadyYzGQKav1zYJ331ki/MWlDLuz0Sxbb1OjL41Plr3Cs9/OBM5ZplawbZABdLpaYzRr1HaIDBm/g8qfuR+TAPIGmwosZlImcKT2SbwAI+hh1mMh1ufOX1RN1bPmZGebgt0fmwIl3FYKoaOcNu2tVebQ0QkikKmq1OlCb3OIRs34vcu1ySGWK/BX3wSCNbvgH144tiHnjhmJLraAeFsvGPMWjzI5XTTPP6+KPLSz9uGs8rrCXrbrSXfu+RPTu3t8s1UMci4Q9EY+Bi/8deHgeY4KsTlKFOKAF7K4nrX6w2uWquDItFks7FNrZcid2xrEoKoth1XgD899ry6v/+n76kzHBInPVaHR46+dCZyxKIbt5Yz7qR4v1uEkRThZjY/foOycMfOhiM7jTf5N2qSGM0hAVvqk5R0WuMMIF2rVGGPSH6uNlr6YFTkjJlycve+0dfp7ypa6PO3KulKwzcmolUpFIJ6Fx4Njvmu+S7l5/ChwaedIEPiRZJCB5NnoC1WJgWlLziIrfh+GD0N3ZoMXkRKNtpFnN07st3c2X0N1rZEw20dYT+dlhCFv2+YaBRNKfmGW85aJ1eWWMNPNj8jwCoKFSGglrDP6J7/MeKOxvDBbiQ8hazGy1xAYmXGeszFrVA5XhMmkJllZeDaqbsyyPv2AhuqqX3YQ09r/QdCFWG0Hi4I8VAnFuecU HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:16 -0700] "GET /M?J=idGulraUzabYPMGwvKbXr3HsMWFGUCPIWtYhw/8mO83cGPI61JP2T4oCwuMPAk8iaEf4t7KXSVJUU/Gfyfp79U4JvlDQLuMtNSEbACZyXZITp7SiB0nE8geYP/K7ydAbSoyeQRc56+SjuJKVNhGYlKdvvBEJwrSoUjfursqc7r2CfXKcstGrLg/ndCt4teb1wiFhM7UOTYtB0RNClx8stZ4VO3JS2N2QD5PKCC6stcsyDoHYi1hHN4myKE0fWmxi2HvgRrGLI8VO0JW4onQ7dO2XGJNdlTelIkvGaCFjsgsTlFvnXfx2Qnlce3VNHs2iBbU0vORJKr7mORVDtVKcjsRZLU8x6cNijFyPTKVPqWOz2C6cFz3K4TGYFsOEyU9K2beUdPEoC3q92MOedhYOTNkvTtufRBxWjCJhmwgJ13Fvd34Xspp60FPlFcQKQAtzDvBNj2iHaRLX8ED0NHU/+oN1nPSd/ZKt6EX6K72J1KjH5mFOPi+teUKhZV1829jZ9PuUvzlzC0Yts4nCKhF5eWFdWFqwVg8Jm4pkZ/WoKszcPhTY7TrK8l1j8Fg9U13YeORj4LSD0QXsqaDhlFRtOwQYDbT/mtf89uYYBg1KCq3jD53M2N58TEiStAofazpPjeIkketjRZb4eGROofdHHctr0/oNcntxNG1BD/mNkeiKMbpwIFksIeLFDU5x7fvirhm7d+Rx2c3J4TZ41mAWSu8r/QumqfaGOnZcIzkkR70SZj5MtCJ6Xk4J/A72YcuZ93IWlMtKP83txlFVIfwUpvNe5/CKB/t HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:18 -0700] "GET /k?o=t74uSOTdxYAY7vOkh0JBI3RQNnoT1vCQmLFgdvkV2vjfHa1YI2XprUDQTZx96xE0ZtTawqncSqyPjdLZlNJkyEN7qGb5XIe+6uLpfPNtlpPbydyLg94y2Q2wkvA87AL/XGy0ezE00N9EzbDf08EQRrUPdaY85iMQjyPnl0IeyEQxJc2M1nEfrwuaFAhp+aCbTC//ns+7A0DosAsPgrhmbwqUgCTPTG5BbbCPtIg3lau+RG9SdR7+VizJfmkbdqN7pMy65Fs3Fl5wd7JyvlSGdYHF9voGCi80Iiv9pFUCthA+Unqfo+vzmjcv6Wa+fsrjuhHXlcTeuYmyXn4k3o1D1aepoAyUu8zKCEWZcD2Te4YXVkxq2wO4AT/khvJAL+ZMdd9CeI7V879ydWDKR6iUAYJgD0IQ9+oJWne8ZOW9q6rao9fx2JkTkO+ZGHLCoM8qp5ziWDKRlo6sUIxjddBUAbCrV33bGoEiXBBsw1y50u1s3iQBKGrxF1h1QyonM3XKxL6hfls/210KC8Kn85XIz3mEzu0d5yjlFxND1Oqwc9GI06BfFiLWX2D8ToSD8zsAVLRqukVxnAh9rWenMJeBeHzpjwPz3tSOmoqp3DJ5sVH3deQCmguQ+kECSKWMFensNQQEtRW6u3aASJzud28QyU+04993yUJt2WYa4+Ysn/r0k5jipvyaKWFVe2m18MbxWH7O4ibo5uHfz4Awu3xMafW8C54qhZz95zyG4sWh7S9Dm+2la1pRVYxN7VfP+ZKdNbwgi6S5L4PBQq+Ou0hFtOC5DAkQyI19JqqyrtIFyWmmX HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:19 -0700] "GET /X?c=ycFuznLMGvNy9jeMIdcseC+NU2indp4CgnecraD6waCUSQisG3I+rEjAp1IpO4ItgXom9vaqjGT3okYo59h2GDuKXvR7tSpdsjCriZicwcBpDTOu/yGZ4sq0wr7+6KvlaVdE9Sc4y+Xfagrt82GCRkuVdwQoIJ2rRIq5RgZZlF7vsocGSr+lHDY0xHQ5mxyuIJgOFvIAaqogayQ+F+wK69pcVAWCGpQFnTm5PNT8yUXpijbmSrtQqeHsIj+a8foDzNTVF2KqVRTqfJ4G9IwT2WeCWWHsfX4sx2k7fGv65i2ZB8EzFe5D2S41R3EeQVTrzjCChtpzpgWPLE5meAwrMAvlQTog5uQGhHNyY/Kqec2iHwV9uOmVSjZJ2aebF+SVK01kGnZufFgkB6wVE5MQ644OWdEo+2k2pKBBm9KbJcFzThyFbCnC1+sbXZoiRXYn3pQy6CmK7AY43Tqzx2QYMbsMFZpmhpgmWylRBUqq6HQAgIwrkHbG2x0pB6GZb/NT3SGvCOqW6zlkL6vbSBZEPS4wKZujdGrZclS3ZLYSMt1MAWFgs9NRP3etfjSpo+l9rbKU4rK9a2cG7CWYVosI1HRLniBvy9Pi+g+brg3NOcyQBZC7lChBLCota0WAMaAeMRvWEt1CDGoJR0UaA+sidQQEnAVq7NUTc8AHNTEEv0yEhc3PfT3el2ddmtBCFvvY7zPiYMhXm2n5Xqo/3wvQm2a0YZrEkxlRCif8r3Ba6XAiMby8/DjhBJG3hsq1e6h7lW6rwDSBTIQvet0uFKVwyJDUwdvWbzVVFNqDdhB/PTbY2uc912aDuwoLSFAK HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:21 -0700] "GET /z?P=zg9l5hvc9REHxPeUWdpuO/Qfou4owR0sCs/L+YV+wuExOIcWpyw3IhSXV8K3nZD+nARFzszPLaVm8SQ4mqvt5JOJnLM8gZd7h2up//eyvVVg7B61TnHM55ywglutii/m0E1Fq63jagSCHVy11uDFyC0M4+O4WrDtCwgYqBQIAZrkV/VtkxlSAWP5SgP/QiAgzdwk6zZrwHaEjeUQu3b1rEabONz08+KFeb18kg03DNBCbgLhJCygAUIfT1Q3Qr0QyWz3oxN3g+jFZm9feWe+ZXo9e8daFpHWXnBtNsW8pWssqKFaGc3BMrFoU8BATwNGsiv8O+8AeSIDSCFNf7rRfA+97qJiAQ56wWqj9eY89cEHtzbPMH/ajHhCNfft0tyiI2H7XuRzBlBP22ESfdQ5spmWOduEa9Hj0OrJkD4nC5LBPHpWr9rd4EDj092h8n0a/WeNUVsuJ1O10v/DYUIqUPBrwQSr4mMw6AHlHDWvYmKFdMXYosO+Cm8Mc22Ict6ll7vAJUoBMdQpAdje20dd92rJTceijAjCOXzICfl5/PUOXa3XigVbj5Czg9lFm2hr4B7kC5ao6O4rxvcqOU7w8i+sHtdGz3hX0o9bohFa3/vGSAypFFyiN3hwk+mheQ3jFFCaBUZoW18oZsieWHhtbeHeD4UFztxrsauVYau5ab1KtsqgjMhoTXphWC3TUc23h//Fx+WQMZgu6AUeI+J5Dpt73W71rXV44J1EGq5vziKwZq6lqGJ2uEgkmOMjGSo5+mfOORp5oaCNVM2BJXXX5NQquoP7KZVVR4/2g9aYTX3orDUumZvHbJ0IsENTw3OlISy0bCw3 HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:24 -0700] "GET /m?t=Berf655sWQS3YzyBNLboQbxjpacmuvMk6CaCTZIvAKBzp+pRDDTxuVIVvxxMA7NEtjYJSFWOWW7KaZIklSvYnXqt4e02aHo62ge7orsK/n/9Fyf2hrGOrZ+eiBdyPLEcTCxTERClsHlTwKBWkT/WyK1xPfGwtK3IvS/3cLEQtLsZ0+u1IiC+EJ5fCuHcxmSrKpYW57ZNm7f1B+TLjwv9jdpdW6Nhp4s7HWaz2RlAetc7NyP06LSNmNiFDvaPxfrUFSJQTVvQOpyNiTahCaf+eqMDVHyubipaCWCssNj9cCTE2bMLPArWQ0sSvM3UyANHkbpADNYoHyAgCU1SlGoYIHJjM/3sUoThRBu01MlA04mpIxO4/Tfp+UMyVI61MMWtUprhmbM5aaALuvL4dUoZ7bdRkb3zjEXoH25V3sTqdQ9rvKZxj7LwylN7xleLWI6T0MABAJSt1IKzg31kLXUrbXANkkdNOC/wWH6q2kQ+J7cWrnAwbQufxMLB1fFhsnRHUp65b7pNjN1uHUIJx8IVaioEe8vicNk/ZJEBpJMsuoX4/7Od4AG97vAH5lEEBSju2rU0BQyjVj8AWf4ghz/d6qh+azcwn7N6lhwWiPQkU3iqcxOVQNCeQh8UuX39yEXkdxnuvIcCkg57ndIQHEbortIViTWXVEnhMDTmeCUgFpVxrdzAXNcIXZreSjThWIZubtCIH28fR5ycMIo88mIqFMdRmESxOSfeNw83/6MqP2/H6/OSXoGvyNe486fkzoecvTa76iYAG/lJcumbHHT0bhr06tNwn6hRgi4KNqlLl3OEtNlueTd0XhQgN1XwlItycYLnNTZbLHxiRbwI1KZCJZ HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:26 -0700] "GET /O?Q=YyQypO+D3V1XweOWBZkojDmJUfpTE+MxVyCnnlvSpU1SyOSpimzKt2tgIZKJ68+CtqZrZWZJP2rwjd/aGqB/VIyXCDXj/pNg85DbXG37HZct7V+QYzCit5X2hhfbKXLyyiGJo/8xdXfnLj5EhXjCS7wBVCypBMNapC5zIvPuvpO2EePeeCwJuysZ7pzN+Cz/jtqzZJ2MwDmzFKFbNc/4x+d5O82+skyz/KQs3orGrZhIkdIZIyQ40Od9/HOHODhrZ5nDZovRjD2FNFoSlxWyptrlAWf1Yuy1s+ssjvwAwi3v5N38EguuyoSEj7fNHZSigjlcOVSBASj1/Ty5YH0Qdz6YQdMXRWlM7p92sjwBU+xHzBEu5ZgmSsnvsdHUN1fvQY3apGOyQeY+NiO7sh4e0tiPA7jSti6/aUjdGE8OMeHlaBZ6u6FnwrDRSJZse+y8PT1loJ1hJtcMibg0vG/exafO2cH8PYjeKjq7NLVeS86maMYoIXdFHiekcrs4lNq4UaREqq8iSOipgREw/9rXqzZlQz/za6X9JTR2niZ5k9ip4rgeZOeMOBzj0tdKYygusoibDrBCAmvqqLhVElfkUOJwUq9QET/AsdtI9iurtHI1Gqu6mvjCLEXUb23AqYUN3xWeqQeeL/ejEJfQp9xWks7cZKRhl+yWu2q1Jom2lzy9PbXYqz7BauaM5mc9nREMUnQWWlIlFRN0CiGE7fhMDw7sGcTiDV8fISWIzn0wULWTY3XMW30LiipthkyQsuKF1gUX1H+Xu1Gk2xS2jLrQ3h9C0LRUtPYe7kNup5/XL5vN5Upn3mcp7RPvkUc8Sz+JfR9lTd2zlvKuUOpni9XoPAvv HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:26 -0700] "GET /B?E=ZYOHTsAMB+KoE7I9eBc86NrwG3uGAtM/b63C04aGbRzVEvr9wirb2g+pSwI5yPnsAgWHzNOXGPGRm/uaYtae+d50DBaB14ID/sWdi4EqSJP7rkf1Tr28wV9ENwcYkZ3iwpl2FygS1vkoTwUW9eaxaQieMmt4olIYye4pH+N5aGfquqJkkReCcNHaR91D8LaLg2Tx20eQ1QYPqDglvKbceeThrpxj6Dl/BQTzQb40fmSOFXp+p/OI/p/1Ieb3lyVEMTW/x2OoWfrXCucLtMmVXXFHOftdIxcZnTGPCM1gYpIEfqbG4T4XVqST13WEh+GUnx87TKTuahiLFuJUTzSydpQ9gkgdNOolgTj7uhPbnWNHnxi6Ddspq7NP73Le90rFmL+moPkX00ZpgHRKYNaJ19aal+6leVE3atxVecB3h2eDebab32e2MdUswzIiQF1Rvw3Iuycz0iPHxN6LQ5qQTusBTYTi1nEZqZDOzT4jB/iMEZ3xtyZABuj77rAmyl6bGBYBxGeODsLqVnnulvzRtcUwLA7wm37hmKbIt3U4hdNUPD7An2tcHf7AXuQdlfb3yw69R5yx5f8CueAWYK3ZtN9r4vNLXGUbNS6FRjjWo1muX0os2dXzuSwEC+KTSqK9iBZwZypuiONtjiIsjMuGbtIewaqmyuTa0ORq0uc/bPe+vR2YKf1z6Aj111it59glfRuzgimbY0RgAiMJkiixRx8vdiZqGqqnZ8xld2sKBQcVwujevy1dH+zJ5geInd/5FK0CtrEApuwfvknew+qKE0qrkqdll3Pv9bDeTDeQNrpmKF+6lIAUfi HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:28 -0700] "GET /B?w=cIQGi5aqe1msapzoDZRgYRDvSjaRh/l+x2F+C7wEOIUuVkt/+w0h6ISZf9byI078PQu6vY39hbFCKTJCJeMLJacEqHSmcUp/7iQGgkHQTt9e06O7rZgTgzD1afRlmvAIcS3dut/r9LyztkR22PcAi1VS5bkr3AqbZvqIEqy/NtyZR8Kd7Oz24+53ovr9aebEAXRvhoLFAZ/R4MeU0yyVSgP5burkTGn0CaiEAs3iP2nSaTvQT8phHFyxjInn0IOBYJLvN/8ZDSs2QUu0CiJLYQ/+nGmvCe/sE5wboSWs5TGal1VbxjTD7XY3IYfExrV5oFchd9B5E4X0TGHruoLsOZFJopcN2B7oAAr8HuVaeL4OUGShqvPHCc9IAcWdZpATiA+g+U6wJOmiP41eI+Z/YmFX9n1GOXacSCZLDxQUh2O26ds9WTizXJJkQYghhZO7yv8A0YFrfIEpozcDtX+bLz43skJsSabe5bOyXzwDdh39z99GHUfMeFhRBOrKQzlbNdBrh7LWa4owng63q3qXJ4Sx7mJAospnlYmW5YlW1NhWfLAqtCtgxyniOZZGEVmgbJNIvbP+Zzq863xo5v4h09GJzb/CD/vQ4nQL2z6XtyIZGV4w1FUUj1qbgR0j3QyMWAyuhVSwoDA4LfFVK78QT3Bksn1nLvIQ8AWFbeGlTzNGkPMU58bec1xOvT+wMWtsOsUXvqd2HHf57HhBCMx1rNDE6d1L10ayKMZgHMdmPyjTjquE2LaSdukL8TkZIzCeYP9rvonE9lituOmJ9DA1tdIcUVKCBbM+dVojE9kSZaFD2/2jFAZ7GVaRXn5FxXvHZbF4YOcTnykPu14d+DWvNEZ5 HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:30 -0700] "GET /x?C=e1gbPALNJKk8Dg3bacpSlCWUYcST0vIKCdUrPCwiiqXjeE0eTs9p/LdmvpYKxoIus96Wmdm8oFN48eVtrXRNfN+ta+YyDKZ7FDpbfi9tQQ5k/H+9CeB7yWEZ9ecyDZud50H2xP1lwwzsKp8yPWSDz5oXDyUTO7fe/TKkqhD93Uy1yk5PAgM5upnhvItr7vsqpYX+t/nx84OTpinTBgZOtsMM19+J3KJF6MLqLA7OkL1kw6V+JvYZmQadzub3dzP9Ml5hC4T58h+0thyNtog9i4tUgNdUZ60HYe16HNL4MMX4kRp+XU00JwmRTHOZgBrhXlMqABlBLjdZ2nXMs73S3341xgJ73vq6luYdkRsSY3Lc/Lmu6MJszm3qRfecBhLVXKF621otrFkd7XUg/sAW02/v0SJNz0h+tJaWLl3uJy9yjy2FWNhLahjPcg8Zg2oujzGzg6yDFtvgQJgAR/R36wCGDJf6JWkDavl/u59wn5/1HkrHP1H2uLCzbIiv3KVZ7arDD6rdfCtjh31YcNynus1CF+QXHD6uE2QG5By6PlAjjfrFz6TOm8cxb99SvfRPPuQQbMyR0K3Z4jKS6vo5MEXNPKj1Z83QrUxT+gRphJ4QPwPHck7UdQjjYd8IQIHXVx3rpDin101vybzrkgKwVLe25cIxaSdDPSEdf5KjBWGPYzoguyvnkOdCMGezcZtKpoBOEpXwCqHWafRnb8mRJZjTSSjqpUc3N/Eka6lQhU8q5DTmv0JVUWYOepU9/7J9Jr87hoXv6AO1Z+iwUNWYvJgoVP6b9eKUneyZQkcqpwe HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:32 -0700] "GET /M?S=E8uHisxar7O9EU+Xj/bjFfG/F0DiJ/jJd3AqJDCDBJTMoRzENkuLNqgHIFa+0Ev+ICB88NJD+GaunKvj2dU4bleSWJnaDUMPTm1IszFqUcStGejs2/731x27mbIbof5MJfu1CINBxu79+tRDAjYvy4X/sh5t11gbDyZ4tUBzvgWXe5uX9/yDCod/4rX2ScADf0pv9QpAbE+IUY+wdmbsEWWjmd5KA6JaVD6p0i15k60LxgY+I+d3OLS25N45UFA6vrwRWc7K7Wv1l7UPOn7GaCeW1Bu7m5w+AXQHbivqN23dFZELQKXHyxypWt9e+E3STO6sqtKIJD2Jgg30zOINlacymc3xlHVnHk0Fl1OROnSkhrXLVxC3jDGS8quWfFg2IaWu7ttb4igc2n507Gqkrv1SCKgdnFg0O4Lxew6gTWEP//AA5oWO+SMVQK8nVG3v9mcwFH1csgJs3h/ee7V1KGy2yBakI5fYAQYoazpUzipBsCYzpIYRjJKHUUio4rqWM/B3Rxt8XfY5+m2mUlqc8mm51Ufu+VJydD7okEXIr55CgWrXPw0V7En05BTyYfc/KSey6I41+b8XSfAU76c39xYxHtVU5L36Lih/CtpWSkhOEPs7jh0amgXGyan1/4LdqiY/bPnWQHClwjhxpB2xd3PnCNvQgkSA1qLVdRKQsCbDFGKl4sVhFizUvBW3B3tE8lBflSTn3fXhvrW63EkFvBc6rn42T5fLHGeMOSnZeM6lM1msx+MOeSC/QP/rHNl3dAKtfnEPprGmvO9Fe72u8ZNfQJj/4Z/e0roAv3dULGggwRn9cZ2lZnTBt HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:34 -0700] "GET /b?o=7vnWl20PrUd+QNVGmjUfWga9pFWKff8BFkCKQo5Cr1IMX+von964Y86V+kq+gVpYalIS7GHVLa4/5C9N7vBZESseEg7nr9aRSZnNHe89cWuiQOWDwwV3bYqBnIC7dxnS04NapCtgowNVUSDiA8Kkaf1DpyNCB9WAZnDFwTwBOeVIaSuh0toG0wNiyABoPIlRLCtIFhBra+iyVYqT2CYYjphKVwCVpk47TXKdcAYRFQCgc71Vdcnqrp3mKh/M2ecL+0UogxM+hwS7mxYdojXKwxTx/mgBMfIfdexKNGErsEoNDvubxJjs2hsfZOqivMDJsWGneKxcfY4GoaC/opJ/YOoKsKAT1uSiBmkVKi2n9y/sp6aGQ9Sr9owYEK4cVXCNHLiQC5gGQ1jNIRphIBRkLgG2osVGjBO380FnOnX25YMzUD3Uf0WjVWmpd/03rc4SM8BWhAmkKJwDeIQe6UuxM51Jmws46w4J6IxCaHSQvT5O5NgNPxd91wpTuNSb5rO1MM5E9VbWSDp5GCjFV1eL4Yu1hZr/r92vUoyUKN5U3tyCzsK+zysYqiaRBMivph6XQCiaZgVW7jaGQiqF9P84bpICSl+B1mLmQuXkKhC6nJ7hDcb9j+9js8WRqNPmw+8RGeNsKTU2fLM5dBZX3pV9bdfyR/BE6h176p5jW1VoAMl1zEVAygAgIB6QGtd0D4qqqVikM8ZOIVQtqQsQDdBlja16QBFrvUTTc2Aj2P6jbABHTaT2EIUjte36ElAJ6htwBq+jJhT4fo6o4RJtsR7q4ZLy+cn9RqPaYy3TNfAvDBK8YLl99WeCmz7KeVKjD4zYEbO8Zp4YdmnyUTUerO HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:35 -0700] "GET /R?f=5hP8oyOR8/Opz/N/LEUR6Guk2RbM5El8jVDT2i/mChl1VVXFyAhzjKMKty9saPIlOIXcIkOCQE12j53726h4pLNgyiNJnk4a0apIRM1yGfWHwjkPoWB6f0tedp2AR5e7w/LQkVOU3F63r9yWUMso3rseRJ6/Rly2naq3BUAi3wPsQDqAvoxJgtTMTpg4gcyhO8kRvS647Qnk4PIvZM1JHpWZA4qj+0ORlOhAECqR9DXdrl62e70sculKKsX/9HDhxtGMj2WDojfo9KDqCF5+XHLF5Ow4CYEtbq/0GkD50z1FlZUxnVYF6A+SoDvzfkz/AmCwHE70e3jZVLG2mG+p1973E94Le+rFdk2pqAwJHKPeOqsI99eKDSYLYhZbS/rT32ZTf2JR1Gcd0zNPLCn7F0mlAJWSpRF54HYxL0gNDN0RHm7m2BtOa9tOohtnSkhqlYou1g1I/RRNAUUwLJkBTC9io4zMKlCxFxHPMjor1BmgWFqNJ8ht9q2kbr8gM3X/EBlU1R2cRJXgRN1Uh3XLlsCYC/fVHTZERyvodbmxEpMF7gFBYucAmOxZoZ/1xFIxX+GXAm+xAlhG3yWmn0ZrTnCaauAuZNYCXx7OJKI9fkWeVn/dxSDz11ORywXLK0chp+sW+bTn6xSgxlm/5PnBp0hqwbQ7KfX8pbYlqy5Q7YGEmrPeKvxkCr4kPzaQ0NGVZLWyAHf1uSNzTLCAXj+EdzyMhB/OB6QgZjZbzR3Q3dWe4YGDYQgaRcro7+GXvKHxGC5SkEa4EZE4CpB36wfjg0jMlXKaQFhSMY5Ls1kFMiGf6tRRFjvaFbqm5vGrl/bhVmtWNMQHrE HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:37 -0700] "GET /r?G=uy+ctb3hcLxv6WOFIKEbWu7dAbIOduHuP6mQfed/oChmrjN5CyTVdSwRcnCIyBFpNzerN5IMLIWR9c+8EwwPS3C2NKaHbX3300SCabhiFEMgijjxwSCLWvuMORKbX7NksAM78Ok92igCdiEdGmD6o8lCP7FKWEJwVd6y3Mchz6BExqz4QjH4OLAog1bJrOjGKCmbyM/8wMnGaMBQ/lo9PKcV7djqOhWSy8YJeY3lYJ3MQt6nuI3aGZn+LvmO/vLTSxxsgoFW+dqSK4eRJkn+zvAJcKTaEbqXgB/y1vQyB9aCtJwPSW559FAHl6V7rTu5yXlz04EmEwM4xUMecJRX2xeE++WF1m//Cz0G9PfRLLIM6nHFk4xn5OQ5aakqE+mc8gq9eQrtxewF1B4bfNY9Wey+p0cJgUdE9f7dVUq5iWLtZ76hmDkXoM6iT4HMiAOezbwgyzTCOt1aGcEhZnJtf+UMCPvgp8lOIvmm39sGVgHNTRhAE9Qg/lRsECjdRqWLL81V3LoJv+pnNKN5XVBgI7uqLAhf0ze+lbh8KH3XFqenVLUdmcXvnpobICLP5x56Xue3DEBJI1Xyt8BBB1+0ZUE1WIovsHOJENDzuG+HTLwPYXu+M9iEdjCAbs2++oihiOVRgaD51ruPY/o+XKaOJ8NJCbsQX7e+HJFuzx+MLuaNcYTya+oaSJbxagsBGG18dAFbvkWCj7N+JKH/nqZMqw1xzgE0Ykf6ii7/cU4MusA5EvfNxVD5DGzixmwgcnRatZTJwb0ccivqi2DoYi0EEzLrF4qKiI5dhHh90kWkihRVLxXIrB7Oa0t+De+ HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:39 -0700] "GET /T?j=jKuqEGUDC8ShFf7CIz8LHhzMH2ccneLxX83ZvV0cg2CZlMVo2qH4fc3F2anfnM+Pi61S+WFTI6sXiZE/2eXscvaj2Va7UsFKh8nkAg6aNJmYmiE8In4wejcVIyYO+4QFknsSO/i7ZAcUvrNZgb+xjSCPXvPBLQxQJ/TsaDczyZME09Xq9RWKr3MqkvwUng69980YaQs67gy/GwPbvJwlMhy0l6+yEfjvUwC+kwmK4tWqHHJe9s96QXpGtTbJwHcFd6WQjIbsK81iWZkDsFgs8nPZN/gxwaWGH907Nw4v2xKe+WVa8u7VVcDeNCNamFLyuVFvP4vtpQEBN12jEhq3Ou/qA/7VnyGUsbMtcCE3C2/dG5ZWPPgUUeFI/9zqi/oR198VrjF8DqTlYRV7jbp7NqmgwTY9+yIic7lhS70PzVn49M35jFcFVyVJhiXVn+lYhz418yUUKAQqt7ZlFit9MYdXfVRmg5nNmVqWfFl0eYTcCgeMtW7JEmf7s1YwTY4Hm7tL2lMrq2WPg6o8SiO44OWApfj2UIk8nENHDPGu5MA0Z7ugIfmV3dKns51AqEnCSnQk/6LTZoSffR9DDQd8K4WjxZcmhhQvY+vWs0fCDxt/pMFyFyAP3ani9/0RC3hrd4YGhGqEMGgkd5qfHgMzHNvRCSnr6d7X+/EDUCr2BofaoEBNGYJJuBIHznCmj2/HlXb8yoTZIRH6rSzg8Ra/ifzqj40nwBjI0pFSV1Nsy41F484mOnIilvmhFfG6X7oglSTJbq4qQHb3JXasgvVFcQbOhju9I0K5obWu7QAMee4SCOnIUhb4szj+74b2PG HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
213.85.255.195 - - [24/Mar/2015:00:17:41 -0700] "GET /g?x=5+1CPLS2BDhJQ1m1flsd89ogv1v86fBNg+oCjIBwJu1Cfx3okOHehwOcti8quPR49GG8pzar0mIcju9YUVsQ5XRViA+4faaffEZOecERxNab3zPkMlaUL3ToJFy6oWMAFvMxAEZsgLI7PPCbDX3QHHLRVaYlGuixJuKhh8B883bH4y4c/NTLvVtLfOWTbXBzVLv0oIRoYOmBjl08y+yHtqXfCzO6y2MKPMhSDpVZLOJeKcrOa14Ey26hLThHXHGwOCRFF9aMuG2QIZ8dBfmcsPPkV0ELm/axrlEu/eyQSgBLeE3Ndv0k+PFRc4EgnLbLpl074xr7vZnthDS1n/C8AGtEp1GXPxuMvaAQNqU/FkcILZZtTQJMVY9gQn08ORMrcLiixLDAN4Swh4dmX0p2nAMEkAqI4oO0vkdI6C9DAWaJjDpAYapXvdM7PEuu04s+NWgPrQCVGERHo4XxFwwf6tWvnW9I4QoiwBP47u7kvlWxDHH4WKdAjNT7wS4dcr9oubEhhhFk4uRHtGWn21l7biJtdxtzkSn+XP8BJRq19VJ1Paj6SL1T HTTP/1.1" 404 73 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
31.184.238.152 - - [24/Mar/2015:00:19:45 -0700] "GET /logs/access.log HTTP/1.1" 200 164175 "http://buy-cytoxan.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36 OPR/20.0.1387.64"
162.244.11.73 - - [24/Mar/2015:00:20:32 -0700] "GET /logs/access.log HTTP/1.1" 200 34504 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:00:20:33 -0700] "GET /logs/access.log HTTP/1.1" 200 164684 "http://ordermobiconlinequickshipping.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
188.165.15.10 - - [24/Mar/2015:00:25:55 -0700] "GET /paper2003/0306JHCol.htm HTTP/1.1" 404 88 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
100.43.91.12 - - [24/Mar/2015:00:26:26 -0700] "GET /Socialist/05MayElection.htm HTTP/1.1" 200 3612 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
31.184.238.152 - - [24/Mar/2015:00:30:44 -0700] "GET /logs/access.log HTTP/1.1" 200 165314 "http://www.theknot.com/wedding/aciclovir-online" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
180.76.6.158 - - [24/Mar/2015:00:31:01 -0700] "GET /Struggle-Archive.htm HTTP/1.1" 200 2287 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
31.184.238.152 - - [24/Mar/2015:00:31:31 -0700] "GET /logs/access.log HTTP/1.1" 200 165772 "http://buy-venlafaxine-75mg.over-blog.com" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
103.14.252.249 - - [24/Mar/2015:00:34:26 -0700] "GET /logs/access.log HTTP/1.1" 200 34931 "https://www.google.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36"
103.246.38.196 - - [24/Mar/2015:00:34:26 -0700] "GET /logs/access.log HTTP/1.1" 200 166025 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; MS-RTC LM 8; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
141.101.31.80 - - [24/Mar/2015:00:38:59 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.1634 Safari/535.19 YE"
141.101.31.80 - - [24/Mar/2015:00:38:59 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; WOW64; U; ru) Presto/2.10.289 Version/12.01"
141.101.31.80 - - [24/Mar/2015:00:39:00 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; WOW64; U; ru) Presto/2.10.289 Version/12.01"
141.101.31.80 - - [24/Mar/2015:00:39:00 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Nichrome/self/19"
141.101.31.80 - - [24/Mar/2015:00:39:00 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Nichrome/self/19"
141.101.31.80 - - [24/Mar/2015:00:39:01 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.91 Safari/537.11"
141.101.31.80 - - [24/Mar/2015:00:39:01 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.91 Safari/537.11"
37.228.107.40 - - [24/Mar/2015:00:39:09 -0700] "GET /pdf/che_sos.pdf HTTP/1.1" 200 207560 "http://www.google.co.in/m?q=free+cheguvera+book+pdf&client=ms-opera-mini&channel=new" "Opera/9.80 (Android; Opera Mini/7.6.35843/36.1370; U; en) Presto/2.12.423 Version/12.16"
31.184.238.152 - - [24/Mar/2015:00:41:50 -0700] "GET /logs/access.log HTTP/1.1" 200 168441 "http://buyfamotidine20mgquickshipping.snack.ws" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [24/Mar/2015:00:42:31 -0700] "GET /logs/access.log HTTP/1.1" 200 168662 "http://doxycycline-100-mg-buy.page.tl" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
27.153.233.108 - - [24/Mar/2015:00:43:30 -0700] "GET /logs/access.log HTTP/1.1" 200 35906 "http://redlug.com/" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"
27.153.233.108 - - [24/Mar/2015:00:43:31 -0700] "GET /socview/SV0302TroublesReview.htm HTTP/1.1" 200 2434 "http://redlug.com/" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"
46.147.146.177 - - [24/Mar/2015:00:44:36 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4356.apishops.ru/" "Opera/9.00 (Windows NT 5.1; U; en)"
46.147.146.177 - - [24/Mar/2015:00:44:37 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4356.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts)"
46.147.146.177 - - [24/Mar/2015:00:44:38 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4356.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; .NET CLR 1.0.2914)"
46.147.146.177 - - [24/Mar/2015:00:44:39 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4356.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.02 Bork-edition [en]"
103.14.252.249 - - [24/Mar/2015:00:46:10 -0700] "GET /logs/access.log HTTP/1.1" 200 35642 "https://www.google.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36"
202.46.55.206 - - [24/Mar/2015:00:47:50 -0700] "GET /socview/04SpringContents.htm HTTP/1.1" 404 89 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:00:52:23 -0700] "GET /logs/access.log HTTP/1.1" 200 170607 "http://ilosone-order-online.soup.io" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:00:53:08 -0700] "GET /logs/access.log HTTP/1.1" 200 170854 "http://tizanidine-buy-no-prescription.snack.ws" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:01:03:11 -0700] "GET /logs/access.log HTTP/1.1" 200 171112 "http://gravatar.com/frapatmerdigati" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
31.184.238.152 - - [24/Mar/2015:01:03:56 -0700] "GET /logs/access.log HTTP/1.1" 200 171376 "http://ordersildalis100mgonlinewithoutprescription.soup.io" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
141.101.31.80 - - [24/Mar/2015:01:07:08 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0"
141.101.31.80 - - [24/Mar/2015:01:07:09 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.1634 Safari/535.19 YE"
141.101.31.80 - - [24/Mar/2015:01:07:09 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.1634 Safari/535.19 YE"
141.101.31.80 - - [24/Mar/2015:01:07:09 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11"
141.101.31.80 - - [24/Mar/2015:01:07:10 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11"
141.101.31.80 - - [24/Mar/2015:01:07:10 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blondebitch.soup.io/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.61"
141.101.31.80 - - [24/Mar/2015:01:07:11 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blondebitch.soup.io/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.61"
66.249.79.35 - - [24/Mar/2015:01:11:55 -0700] "GET /images/150203/YaWBelfast1.jpg HTTP/1.1" 200 19541 "-" "Googlebot-Image/1.0"
78.58.143.166 - - [24/Mar/2015:01:11:59 -0700] "GET /logs/access.log/RK=0/RS=3pBGsDoyNk_9CI1_kCqOS2vIjHE- HTTP/1.1" 404 88 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
78.58.143.166 - - [24/Mar/2015:01:11:59 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:01:13:52 -0700] "GET /logs/access.log HTTP/1.1" 200 173881 "http://diclofenac-buy-online.snack.ws" "Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0"
31.184.238.152 - - [24/Mar/2015:01:14:36 -0700] "GET /logs/access.log HTTP/1.1" 200 174093 "http://aripiprazole-20mg-buy-cheap.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:01:24:38 -0700] "GET /logs/access.log HTTP/1.1" 200 174376 "http://buydesogenonline.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:01:25:21 -0700] "GET /logs/access.log HTTP/1.1" 200 174619 "http://order-azithromycin-250mg.soup.io" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
89.140.152.184 - - [24/Mar/2015:01:29:17 -0700] "GET / HTTP/1.1" 200 1273 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1"
31.184.238.152 - - [24/Mar/2015:01:35:11 -0700] "GET /logs/access.log HTTP/1.1" 200 175036 "http://buy-famvir-500mg-cheap.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
141.101.31.80 - - [24/Mar/2015:01:35:28 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20100101 Firefox/15.0.1"
141.101.31.80 - - [24/Mar/2015:01:35:29 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; Edition Yx) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [24/Mar/2015:01:35:29 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; Edition Yx) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [24/Mar/2015:01:35:30 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.2; WOW64; MRA 8.0 (build 5784)) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [24/Mar/2015:01:35:30 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.2; WOW64; MRA 8.0 (build 5784)) Presto/2.12.388 Version/12.11"
141.101.31.80 - - [24/Mar/2015:01:35:30 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0"
141.101.31.80 - - [24/Mar/2015:01:35:31 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0"
31.184.238.152 - - [24/Mar/2015:01:44:53 -0700] "GET /logs/access.log HTTP/1.1" 200 176813 "http://cabergoline-05mg-buy-without-rx.soup.io" "Opera/9.80 (Windows NT 6.1; Win64; x64) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [24/Mar/2015:01:45:30 -0700] "GET /logs/access.log HTTP/1.1" 200 177038 "http://order-motilium.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 OPR/19.0.1326.63"
180.76.6.51 - - [24/Mar/2015:01:45:41 -0700] "GET /paperarticles/?C=N;O=A HTTP/1.1" 200 1735 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
100.43.81.131 - - [24/Mar/2015:01:46:01 -0700] "GET /logs/access_140823.log HTTP/1.1" 200 1535429 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
148.251.75.46 - - [24/Mar/2015:01:49:47 -0700] "GET /LabHist/ContentsList.htm HTTP/1.1" 200 30482 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"
66.249.79.27 - - [24/Mar/2015:01:53:27 -0700] "GET /YaW/DayXPoster2_files/image001.gif HTTP/1.1" 404 88 "-" "Googlebot-Image/1.0"
31.184.238.152 - - [24/Mar/2015:01:54:31 -0700] "GET /logs/access.log HTTP/1.1" 200 178065 "http://repaglinide1mgbg.forumcircle.com" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:02:40 -0700] "GET /logs/access.log HTTP/1.1" 200 178316 "http://cabergoline-025mg-order-no-prescription.soup.io" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:03:21 -0700] "GET /logs/access.log HTTP/1.1" 200 178582 "http://gravatar.com/sorcontrorostjackja" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
141.101.31.80 - - [24/Mar/2015:02:03:23 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 5.1; Edition Ukraine Local) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [24/Mar/2015:02:03:23 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0"
141.101.31.80 - - [24/Mar/2015:02:03:24 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0"
141.101.31.80 - - [24/Mar/2015:02:03:24 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.39 Version/11.00"
141.101.31.80 - - [24/Mar/2015:02:03:24 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.7.39 Version/11.00"
141.101.31.80 - - [24/Mar/2015:02:03:25 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.12 (KHTML, like Gecko) Maxthon/3.0 Chrome/18.0.966.0 Safari/535.12"
141.101.31.80 - - [24/Mar/2015:02:03:26 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.12 (KHTML, like Gecko) Maxthon/3.0 Chrome/18.0.966.0 Safari/535.12"
157.55.39.217 - - [24/Mar/2015:02:09:18 -0700] "GET /logs/access_140512.log HTTP/1.1" 404 88 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
142.54.184.181 - - [24/Mar/2015:02:10:43 -0700] "GET / HTTP/1.1" 200 1273 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
142.54.184.181 - - [24/Mar/2015:02:10:45 -0700] "GET / HTTP/1.1" 200 1273 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.0.3705)"
31.184.238.152 - - [24/Mar/2015:02:11:36 -0700] "GET /logs/access.log HTTP/1.1" 200 180883 "http://strattera-10mg-buy-cheap.soup.io" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.13014 YaBrowser/13.12.1599.13014 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:12:15 -0700] "GET /logs/access.log HTTP/1.1" 200 181170 "http://gravatar.com/topkbulboburomes" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.44.93.25 - - [24/Mar/2015:02:16:44 -0700] "GET /logs/access.log HTTP/1.1" 200 37566 "https://www.google.ru/" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
157.55.39.237 - - [24/Mar/2015:02:18:56 -0700] "GET /paper2003/0306France.htm HTTP/1.1" 200 3979 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
31.184.238.152 - - [24/Mar/2015:02:20:46 -0700] "GET /logs/access.log HTTP/1.1" 200 181849 "http://lansoprazole-15mg-buy-online.snack.ws" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:21:22 -0700] "GET /logs/access.log HTTP/1.1" 200 182104 "http://order-acetazolamide-no-rx.snack.ws" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [24/Mar/2015:02:29:32 -0700] "GET /logs/access.log HTTP/1.1" 200 182319 "http://eksustiva600mg.forumcircle.com" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:30:09 -0700] "GET /logs/access.log HTTP/1.1" 200 182597 "http://orderbudesonideonlineie.over-blog.com" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36"
101.251.211.237 - - [24/Mar/2015:02:30:21 -0700] "GET /logs/access.log HTTP/1.1" 200 37761 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
141.101.31.80 - - [24/Mar/2015:02:31:16 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Opera/9.80 (Windows NT 6.1; MRA 6.0 (build 5976)) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [24/Mar/2015:02:31:31 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0"
141.101.31.80 - - [24/Mar/2015:02:31:32 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0"
141.101.31.80 - - [24/Mar/2015:02:31:32 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2"
141.101.31.80 - - [24/Mar/2015:02:31:33 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2"
141.101.31.80 - - [24/Mar/2015:02:31:33 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1; rv:7.0) Gecko/20100101 Firefox/7.0"
141.101.31.80 - - [24/Mar/2015:02:31:34 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://blonde.aircus.com/" "Mozilla/5.0 (Windows NT 5.1; rv:7.0) Gecko/20100101 Firefox/7.0"
66.249.79.43 - - [24/Mar/2015:02:32:16 -0700] "GET /images/logos/backup.gif HTTP/1.1" 200 51 "-" "Googlebot-Image/1.0"
31.184.238.152 - - [24/Mar/2015:02:38:27 -0700] "GET /logs/access.log HTTP/1.1" 200 184710 "http://lamprene-50mg-buy-no-prescription.soup.io" "Opera/9.80 (Windows NT 6.1) Presto/2.12.388 Version/12.16"
31.184.238.152 - - [24/Mar/2015:02:39:07 -0700] "GET /logs/access.log HTTP/1.1" 200 184925 "http://yasmin-order.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:48:00 -0700] "GET /logs/access.log HTTP/1.1" 200 185193 "http://gravatar.com/freeftherfmemnakompai" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:48:39 -0700] "GET /logs/access.log HTTP/1.1" 200 185446 "http://www.theknot.com/wedding/trandate-and-no" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
219.142.192.196 - - [24/Mar/2015:02:55:11 -0700] "GET /logs/access.log HTTP/1.1" 200 38039 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
176.25.159.80 - - [24/Mar/2015:02:56:15 -0700] "GET /logs/access_140427.log HTTP/1.1" 404 88 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:02:57:08 -0700] "GET /logs/access.log HTTP/1.1" 200 186209 "http://buygriseofulvin.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68"
31.184.238.152 - - [24/Mar/2015:02:57:50 -0700] "GET /logs/access.log HTTP/1.1" 200 186475 "http://ordercetirizineonline.snack.ws" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0"
141.101.31.80 - - [24/Mar/2015:02:58:55 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 5.1; Edition Yx) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [24/Mar/2015:02:58:57 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [24/Mar/2015:02:58:57 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [24/Mar/2015:02:58:58 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [24/Mar/2015:02:58:58 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
141.101.31.80 - - [24/Mar/2015:02:58:58 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; U; Edition Yx; ru) Presto/2.10.289 Version/12.02"
141.101.31.80 - - [24/Mar/2015:02:58:59 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; U; Edition Yx; ru) Presto/2.10.289 Version/12.02"
203.106.214.137 - - [24/Mar/2015:03:01:10 -0700] "GET /logs/access.log HTTP/1.1" 200 38244 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
46.147.146.177 - - [24/Mar/2015:03:01:40 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4689.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.1.4322)"
46.147.146.177 - - [24/Mar/2015:03:01:40 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4689.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.1.4322)"
46.147.146.177 - - [24/Mar/2015:03:01:41 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4689.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
46.147.146.177 - - [24/Mar/2015:03:01:42 -0700] "GET / HTTP/1.1" 200 9589 "http://msk4689.apishops.ru/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.11 [en]"
188.165.15.10 - - [24/Mar/2015:03:04:02 -0700] "GET /LabHist/LabHist/17yearold.htm HTTP/1.1" 404 88 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"
31.184.238.152 - - [24/Mar/2015:03:06:28 -0700] "GET /logs/access.log HTTP/1.1" 200 189524 "http://buy-sucralfate-1000mg-online.soup.io" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36"
157.55.39.237 - - [24/Mar/2015:03:07:02 -0700] "GET /Election/031108TB.htm HTTP/1.1" 200 1042 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
31.184.238.152 - - [24/Mar/2015:03:07:05 -0700] "GET /logs/access.log HTTP/1.1" 200 189964 "http://ordernaproxen250mg.forumcircle.com" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"
117.169.1.19 - - [24/Mar/2015:03:09:53 -0700] "GET /logs/access.log HTTP/1.1" 200 38454 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
85.214.230.139 - - [24/Mar/2015:03:10:10 -0700] "GET /logs/access.log HTTP/1.1" 200 38286 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:03:16:03 -0700] "GET /logs/access.log HTTP/1.1" 200 190709 "http://ordercetirizinecheap.snack.ws" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
103.246.38.196 - - [24/Mar/2015:03:16:09 -0700] "GET /logs/access.log HTTP/1.1" 200 190957 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; MS-RTC LM 8; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
170.252.160.1 - - [24/Mar/2015:03:16:10 -0700] "GET /logs/access.log HTTP/1.1" 200 38358 "https://www.google.co.in/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:03:16:41 -0700] "GET /logs/access.log HTTP/1.1" 200 191468 "http://glucotrol-order.soup.io" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
74.67.210.175 - - [24/Mar/2015:03:17:06 -0700] "GET /logs/access.log HTTP/1.1" 200 38600 "https://www.google.co.uk/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:03:24:48 -0700] "GET /logs/access.log HTTP/1.1" 200 191952 "http://gravatar.com/chemburelanlinktea" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
31.7.232.102 - - [24/Mar/2015:03:24:53 -0700] "GET /logs/access.log HTTP/1.1" 200 38479 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:03:25:27 -0700] "GET /logs/access.log HTTP/1.1" 200 192446 "http://orderlinezolid600mgonline.snack.ws" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"
141.101.31.80 - - [24/Mar/2015:03:26:38 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; U; ru) Presto/2.10.289 Version/12.01"
141.101.31.80 - - [24/Mar/2015:03:26:38 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; Edition Yx) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [24/Mar/2015:03:26:38 -0700] "GET /access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Opera/9.80 (Windows NT 6.1; WOW64; Edition Yx) Presto/2.12.388 Version/12.10"
141.101.31.80 - - [24/Mar/2015:03:26:39 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.0; rv:17.0) Gecko/20100101 Firefox/17.0"
141.101.31.80 - - [24/Mar/2015:03:26:39 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.0; rv:17.0) Gecko/20100101 Firefox/17.0"
141.101.31.80 - - [24/Mar/2015:03:26:39 -0700] "GET /logs/access_130930.log HTTP/1.1" 404 73 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"
141.101.31.80 - - [24/Mar/2015:03:26:40 -0700] "GET /access_130930.log HTTP/1.1" 404 89 "http://pristiq.forumcircle.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"
37.59.131.238 - - [24/Mar/2015:03:26:49 -0700] "GET /LabHist/ContentsList.htm HTTP/1.1" 200 12093 "http://redlug.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
31.184.238.152 - - [24/Mar/2015:03:33:28 -0700] "GET /logs/access.log HTTP/1.1" 200 194447 "http://order-ethionamide-250mg-without-rx.snack.ws" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.15"
31.184.238.152 - - [24/Mar/2015:03:34:05 -0700] "GET /logs/access.log HTTP/1.1" 200 194671 "http://gravatar.com/agridelnapande" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
84.203.78.80 - - [24/Mar/2015:03:37:17 -0700] "GET /socview/0306SCW.htm HTTP/1.1" 200 5294 "http://www.google.ie/url?sa=t&source=web&cd=10&ved=0CDsQFjAJ&url=http%3A%2F%2Fredlug.com%2Fsocview%2F0306SCW.htm&rct=j&q=the%20blue%20shirts%20in%20spain&ei=vD0RVbjQNM3e7AbqpoDoCw&usg=AFQjCNGa47mJ-C5rv-LJa84XqMF0199ErA" "Mozilla/5.0 (Linux; U; Android 4.4.2; en-gb; HTC_Desire_610 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"
84.203.78.80 - - [24/Mar/2015:03:37:17 -0700] "GET /cwi.css HTTP/1.1" 404 73 "http://redlug.com/socview/0306SCW.htm" "Mozilla/5.0 (Linux; U; Android 4.4.2; en-gb; HTC_Desire_610 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"
217.12.206.140 - - [24/Mar/2015:03:38:29 -0700] "GET / HTTP/1.1" 200 1273 "http://redlug.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
@@ -0,0 +1,8 @@
aaaaaaaabbbbbbbbaaaaaaaabbbbbbbb
aaaaaaaaabbbbbbbbbaaaaaaaaabbbbbbbbb
aaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbb
aaaaaaaaaaabbbbbbbbbbbaaaaaaaaaaabbbbbbbbbbb
aaaaaaaaaaaabbbbbbbbbbbbaaaaaaaaaaaabbbbbbbbbbbb
aaaaaaaaaaaaabbbbbbbbbbbbbaaaaaaaaaaaaabbbbbbbbbbbbb
aaaaaaaaaaaaaabbbbbbbbbbbbbbaaaaaaaaaaaaaabbbbbbbbbbbbbb
aaaaaaaaaaaaaaabbbbbbbbbbbbbbbaaaaaaaaaaaaaaabbbbbbbbbbbbbbb
@@ -0,0 +1,5 @@
aaaabbbbaaaabbbbaaaabbbbaaaabbbb
aaaaabbbbbaaaaabbbbbaaaaabbbbbaaaaabbbbb
aaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbb
aaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbb
aaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbb
@@ -0,0 +1,7 @@
aabbaabbaabbaabbaabbaabbaabbaabb
aaabbbaaabbbaaabbbaaabbbaaabbbaaabbbaaabbbaaabbb
aaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbb
aaaaabbbbbaaaaabbbbbaaaaabbbbbaaaaabbbbbaaaaabbbbbaaaaabbbbbaaaaabbbbbaaaaabbbbb
aaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbbaaaaaabbbbbb
aaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbbaaaaaaabbbbbbb
aaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbbaaaaaaaabbbbbbbb
@@ -0,0 +1,1000 @@
2014-10-18T06:53:32Z
2014-10-09T14:30:40Z
2014-07-10T07:00:39Z
2015-02-26T17:12:11Z
2014-06-14T16:59:18Z
2014-10-16T09:28:32Z
2014-08-23T04:10:40Z
2014-09-23T00:21:17Z
2015-03-14T02:40:17Z
2014-04-25T12:44:27Z
2014-10-06T09:02:36Z
2014-12-16T08:22:18Z
2014-08-04T10:22:38Z
2014-11-11T22:19:27Z
2014-09-28T01:07:49Z
2014-08-31T22:10:33Z
2014-08-19T07:26:59Z
2014-05-23T06:50:28Z
2014-03-20T10:12:05Z
2014-04-09T08:07:59Z
2014-11-21T20:33:02Z
2014-12-12T04:11:12Z
2014-10-10T20:27:05Z
2015-01-17T15:27:59Z
2014-03-17T08:48:11Z
2014-03-24T17:22:11Z
2014-05-07T22:33:44Z
2014-05-18T05:20:45Z
2014-09-12T20:29:07Z
2014-09-14T03:16:32Z
2014-09-21T16:59:39Z
2014-03-27T12:23:39Z
2014-03-25T06:41:42Z
2014-03-31T08:13:05Z
2014-12-25T10:31:49Z
2014-06-04T07:21:54Z
2014-06-17T09:19:07Z
2014-11-22T09:53:46Z
2014-10-21T14:43:15Z
2014-10-27T06:37:14Z
2014-05-26T21:12:36Z
2014-07-03T14:26:01Z
2015-02-25T23:26:30Z
2014-12-12T14:34:22Z
2014-04-25T04:26:39Z
2014-07-28T15:24:18Z
2014-11-06T00:39:44Z
2014-10-25T22:31:42Z
2014-07-17T21:05:11Z
2015-02-13T12:21:38Z
2014-04-14T12:27:29Z
2015-01-06T16:19:03Z
2014-08-20T08:49:53Z
2014-04-08T23:22:14Z
2014-03-30T21:24:10Z
2014-10-20T23:50:29Z
2014-07-14T16:27:39Z
2014-12-22T02:08:20Z
2014-08-08T06:04:33Z
2015-02-21T23:49:09Z
2014-11-03T06:18:29Z
2014-06-10T15:42:15Z
2014-06-18T00:18:33Z
2014-10-15T11:27:51Z
2014-10-27T04:12:42Z
2014-11-18T00:56:54Z
2014-12-22T12:11:15Z
2014-10-23T01:33:00Z
2014-07-06T16:56:58Z
2014-12-24T19:12:34Z
2014-07-07T08:46:40Z
2014-04-02T10:06:44Z
2015-02-23T09:02:56Z
2015-01-01T09:11:48Z
2015-01-13T12:35:20Z
2014-03-27T18:39:41Z
2014-10-15T04:58:34Z
2014-12-15T02:11:03Z
2014-08-20T15:02:55Z
2015-01-20T06:42:43Z
2014-05-05T19:49:17Z
2014-11-13T05:54:09Z
2014-11-17T14:28:23Z
2014-04-08T02:34:51Z
2014-11-01T01:16:32Z
2014-10-28T03:56:45Z
2014-07-14T02:54:57Z
2014-05-22T23:24:55Z
2014-08-15T16:46:19Z
2014-08-12T21:38:24Z
2014-10-13T01:57:32Z
2014-12-07T16:52:55Z
2015-03-11T23:33:57Z
2014-06-11T09:54:05Z
2014-08-25T23:13:47Z
2014-05-09T04:21:48Z
2014-08-12T16:39:34Z
2015-02-01T07:53:51Z
2014-09-26T08:12:32Z
2014-03-30T11:00:24Z
2014-10-15T19:00:10Z
2014-10-10T21:08:08Z
2014-10-20T13:29:19Z
2015-01-11T18:43:52Z
2014-12-13T22:18:59Z
2014-11-26T14:09:21Z
2014-09-03T21:00:48Z
2014-08-26T05:57:42Z
2014-07-12T09:17:07Z
2014-12-01T06:33:12Z
2014-04-25T14:48:03Z
2014-03-27T04:42:07Z
2014-04-02T11:43:29Z
2014-11-04T06:25:55Z
2014-12-29T10:28:32Z
2014-09-15T07:23:37Z
2014-11-13T14:23:35Z
2015-03-14T06:02:09Z
2015-01-16T02:13:46Z
2014-07-06T20:31:07Z
2014-08-02T08:05:38Z
2014-09-26T02:29:40Z
2014-10-23T02:13:30Z
2014-04-24T02:34:32Z
2014-11-11T11:37:10Z
2014-12-13T14:02:33Z
2014-11-16T23:18:41Z
2014-05-25T18:55:03Z
2015-01-26T15:09:38Z
2014-05-02T22:46:12Z
2014-06-24T14:43:30Z
2014-10-28T01:30:39Z
2014-08-14T13:11:23Z
2014-03-30T06:34:33Z
2014-12-24T05:51:36Z
2015-01-18T20:09:03Z
2014-10-01T05:36:18Z
2015-02-05T00:47:58Z
2015-01-12T19:13:29Z
2014-10-25T08:07:51Z
2014-03-21T08:26:10Z
2015-02-18T22:33:40Z
2015-02-01T17:50:33Z
2014-05-16T06:52:25Z
2014-08-08T00:41:17Z
2014-12-15T12:35:56Z
2014-10-28T15:42:29Z
2014-07-14T04:40:23Z
2014-05-19T21:04:07Z
2014-12-25T17:40:12Z
2015-01-27T07:36:26Z
2015-03-15T22:24:13Z
2015-02-13T19:47:07Z
2014-10-19T13:36:42Z
2014-03-18T05:50:06Z
2015-02-10T18:06:18Z
2014-05-10T12:17:12Z
2014-11-15T06:26:19Z
2014-09-11T17:01:17Z
2014-03-27T13:46:47Z
2014-12-20T07:36:15Z
2015-03-08T12:10:34Z
2014-06-07T14:01:37Z
2014-10-14T06:25:57Z
2014-05-21T15:11:02Z
2015-01-12T11:10:34Z
2014-09-19T03:43:56Z
2014-04-30T09:14:30Z
2014-04-14T11:16:12Z
2014-03-18T03:11:44Z
2014-09-17T13:32:44Z
2014-12-21T13:59:15Z
2014-07-28T20:50:30Z
2014-10-01T16:37:51Z
2014-08-31T08:44:20Z
2014-07-04T11:13:12Z
2014-04-28T02:57:19Z
2015-01-16T00:21:07Z
2014-06-08T05:58:35Z
2015-02-10T13:26:51Z
2014-09-21T07:07:19Z
2014-11-13T10:01:00Z
2015-03-13T21:28:41Z
2014-07-09T13:19:17Z
2015-02-03T18:27:51Z
2014-04-15T08:56:11Z
2014-08-27T02:59:51Z
2014-03-27T09:31:28Z
2014-09-26T18:29:01Z
2014-08-01T20:20:35Z
2014-10-18T13:42:35Z
2014-10-31T21:03:20Z
2014-06-30T23:18:16Z
2014-12-23T19:06:31Z
2015-01-19T02:37:28Z
2014-05-17T19:56:18Z
2014-07-25T06:13:43Z
2014-05-13T10:37:42Z
2014-06-29T04:07:57Z
2015-03-08T16:04:57Z
2014-06-11T11:18:31Z
2014-09-27T20:40:15Z
2014-12-19T06:53:06Z
2014-11-11T13:31:30Z
2014-05-09T23:15:03Z
2014-04-17T21:07:58Z
2014-05-09T07:58:38Z
2014-10-01T02:35:19Z
2014-07-16T20:38:52Z
2014-03-17T06:17:05Z
2014-05-23T08:38:51Z
2014-07-08T21:03:38Z
2014-05-08T14:21:08Z
2015-01-21T13:53:31Z
2014-03-30T09:43:52Z
2014-06-04T21:58:28Z
2014-03-31T07:25:05Z
2014-08-11T07:48:22Z
2014-08-18T12:34:33Z
2014-09-30T13:09:26Z
2014-10-09T00:46:34Z
2014-07-01T10:59:03Z
2014-04-20T20:19:06Z
2014-06-12T20:22:45Z
2014-10-14T04:15:26Z
2014-03-23T01:52:23Z
2014-07-12T22:11:59Z
2014-04-10T06:43:59Z
2015-01-23T15:28:18Z
2014-12-15T15:14:27Z
2015-01-11T03:04:12Z
2015-01-13T11:20:19Z
2014-06-10T11:06:37Z
2014-05-18T23:50:59Z
2014-12-06T23:54:39Z
2014-04-30T05:59:31Z
2014-08-06T02:07:01Z
2014-12-20T08:55:52Z
2014-06-03T15:49:52Z
2014-05-31T04:04:36Z
2014-04-24T11:15:44Z
2014-11-09T21:41:37Z
2014-08-05T22:41:27Z
2014-06-24T02:51:56Z
2014-08-11T20:34:51Z
2014-08-05T17:42:06Z
2014-10-26T18:22:25Z
2014-07-29T00:01:30Z
2014-12-12T16:37:04Z
2014-06-26T15:25:09Z
2014-08-05T05:15:21Z
2014-05-05T05:41:55Z
2015-03-08T21:25:32Z
2015-01-20T15:25:46Z
2014-10-02T20:22:17Z
2014-08-30T13:33:43Z
2014-09-22T09:03:09Z
2014-10-27T10:30:39Z
2014-04-15T20:00:05Z
2015-02-28T09:58:59Z
2014-10-27T22:35:14Z
2014-07-30T12:34:31Z
2014-06-23T09:34:58Z
2015-01-19T08:30:42Z
2014-12-28T14:23:13Z
2014-10-28T15:34:19Z
2015-02-03T00:17:31Z
2014-05-20T07:51:23Z
2014-09-17T10:02:29Z
2014-03-17T14:40:31Z
2014-12-06T23:13:06Z
2014-08-06T08:42:59Z
2014-06-28T16:10:54Z
2014-06-11T21:18:23Z
2015-01-05T19:50:46Z
2015-02-09T16:19:38Z
2014-05-27T12:33:08Z
2015-01-17T04:26:09Z
2015-02-12T19:31:04Z
2014-03-31T22:57:38Z
2014-03-25T05:06:25Z
2014-10-11T00:41:05Z
2014-04-30T08:02:04Z
2015-01-23T06:57:01Z
2014-06-09T04:08:39Z
2014-06-15T06:29:29Z
2014-05-06T00:06:25Z
2014-05-03T04:18:39Z
2014-10-10T21:23:34Z
2014-05-19T17:09:48Z
2014-04-21T20:15:50Z
2014-04-02T01:06:38Z
2014-05-10T14:57:10Z
2014-06-29T15:38:07Z
2014-06-07T23:57:36Z
2014-04-09T12:32:20Z
2014-07-27T15:16:18Z
2014-03-21T02:46:02Z
2014-07-23T00:26:44Z
2015-02-03T18:26:23Z
2014-12-09T04:27:10Z
2014-11-08T19:28:55Z
2014-10-03T08:34:41Z
2015-01-31T15:01:33Z
2015-01-12T15:53:27Z
2014-11-18T22:11:27Z
2014-09-19T02:14:40Z
2014-11-20T20:51:51Z
2014-06-30T19:00:14Z
2014-11-03T19:49:47Z
2014-03-16T12:12:18Z
2014-09-16T08:21:38Z
2015-03-09T03:32:19Z
2014-09-02T13:56:54Z
2014-08-22T14:27:10Z
2014-03-16T10:51:23Z
2015-01-06T06:33:54Z
2014-12-25T08:04:51Z
2014-10-17T07:44:33Z
2015-02-06T02:56:40Z
2015-02-03T11:09:34Z
2015-03-05T11:52:00Z
2014-08-11T15:10:55Z
2014-10-07T05:58:37Z
2014-10-19T05:52:49Z
2014-09-27T14:53:26Z
2015-02-22T11:22:25Z
2014-09-20T12:37:56Z
2015-01-13T09:54:13Z
2014-12-12T03:29:14Z
2014-09-22T17:19:18Z
2014-05-09T12:20:36Z
2014-04-14T00:06:29Z
2015-01-04T01:41:59Z
2014-10-20T22:30:11Z
2014-11-27T01:10:14Z
2015-01-26T00:22:30Z
2014-06-05T10:42:20Z
2015-03-14T07:04:40Z
2014-10-08T16:23:50Z
2015-01-26T23:54:32Z
2015-01-30T20:52:01Z
2014-09-03T10:39:02Z
2015-03-10T02:43:31Z
2014-12-17T08:27:08Z
2014-04-21T13:06:21Z
2014-05-02T00:09:16Z
2014-11-22T21:40:44Z
2015-01-06T00:15:59Z
2014-10-22T21:29:15Z
2014-07-24T21:39:17Z
2014-10-05T03:10:25Z
2015-02-24T04:44:04Z
2015-03-05T13:22:15Z
2014-10-27T11:38:41Z
2014-04-02T06:13:23Z
2015-01-09T00:30:34Z
2014-07-02T23:15:04Z
2014-04-28T17:49:38Z
2014-11-03T00:40:04Z
2014-07-18T03:02:13Z
2014-12-22T02:11:21Z
2014-07-22T17:17:19Z
2015-03-07T21:08:28Z
2014-05-11T00:14:43Z
2015-01-08T13:26:39Z
2014-05-09T11:26:14Z
2014-06-07T06:03:53Z
2014-10-29T23:47:07Z
2014-10-12T16:11:37Z
2014-06-21T18:24:31Z
2014-09-30T00:31:34Z
2014-07-14T03:03:29Z
2014-07-26T05:38:30Z
2015-01-17T04:02:12Z
2014-10-17T01:21:22Z
2014-08-10T10:26:51Z
2015-03-15T22:41:06Z
2015-02-22T18:50:30Z
2014-05-29T05:44:25Z
2014-12-14T00:37:58Z
2014-05-04T07:43:27Z
2014-09-20T13:52:24Z
2014-10-26T10:44:05Z
2014-05-01T09:15:17Z
2014-03-21T04:02:36Z
2014-09-21T15:31:45Z
2015-02-06T10:08:46Z
2014-11-19T18:20:53Z
2015-01-14T14:46:27Z
2014-07-05T21:45:24Z
2015-01-01T18:18:35Z
2014-10-04T09:12:17Z
2014-04-27T00:08:37Z
2014-08-19T03:19:30Z
2015-03-09T21:40:21Z
2014-04-21T16:08:23Z
2014-12-27T12:11:09Z
2014-04-26T15:04:53Z
2014-09-25T20:41:36Z
2014-05-08T21:35:32Z
2014-07-12T20:18:26Z
2014-12-31T05:29:53Z
2014-06-24T23:00:11Z
2014-04-05T07:33:14Z
2014-07-03T12:07:16Z
2014-05-25T19:32:38Z
2014-08-27T01:12:05Z
2014-06-04T00:01:29Z
2014-04-03T08:37:15Z
2014-05-25T16:00:15Z
2014-10-17T01:00:00Z
2014-05-26T02:28:11Z
2015-01-31T02:12:38Z
2014-11-22T23:25:47Z
2014-03-21T01:57:24Z
2014-10-12T11:01:23Z
2014-07-29T23:32:46Z
2014-11-08T00:12:40Z
2014-03-31T22:37:52Z
2014-12-30T13:26:56Z
2014-05-11T05:31:13Z
2015-01-15T14:26:37Z
2014-07-09T20:50:50Z
2014-09-08T05:10:14Z
2014-05-15T11:56:48Z
2015-02-03T19:25:18Z
2014-04-08T04:14:15Z
2014-10-27T22:53:44Z
2015-02-05T09:17:46Z
2014-07-12T11:16:10Z
2014-04-29T04:40:59Z
2015-01-02T04:55:25Z
2014-12-17T23:40:28Z
2014-08-24T15:24:50Z
2014-09-01T03:49:15Z
2014-05-14T01:20:46Z
2014-09-27T17:26:58Z
2015-02-27T12:16:12Z
2014-09-04T22:03:20Z
2014-06-07T10:21:12Z
2014-08-14T04:26:57Z
2014-06-24T22:39:35Z
2014-04-17T20:25:30Z
2014-09-25T19:26:55Z
2015-01-27T03:23:12Z
2014-07-24T13:40:34Z
2014-09-11T13:00:12Z
2014-07-10T14:14:23Z
2014-11-07T11:35:00Z
2014-08-05T15:32:10Z
2014-11-22T17:01:58Z
2014-05-09T03:11:36Z
2015-01-17T12:37:47Z
2014-04-18T09:02:12Z
2014-10-09T12:17:06Z
2014-12-03T14:57:54Z
2015-01-30T00:03:47Z
2014-10-24T21:41:15Z
2014-05-07T13:39:16Z
2015-01-18T12:17:09Z
2014-04-22T23:08:24Z
2014-09-15T21:27:14Z
2014-09-02T02:17:47Z
2014-05-27T01:43:41Z
2015-03-03T17:59:15Z
2014-05-28T12:46:58Z
2014-05-03T15:30:40Z
2014-11-02T08:52:12Z
2014-03-19T06:13:00Z
2014-12-14T12:01:22Z
2014-05-21T21:32:06Z
2015-01-29T16:40:58Z
2015-01-24T01:48:58Z
2015-01-23T20:36:18Z
2015-01-19T10:02:17Z
2015-01-10T02:56:34Z
2014-12-04T11:27:41Z
2014-08-24T09:21:31Z
2014-11-24T04:20:48Z
2014-08-29T12:22:30Z
2015-02-14T13:36:01Z
2014-12-17T06:10:05Z
2014-08-28T14:24:25Z
2014-06-07T19:36:31Z
2014-12-27T14:20:20Z
2014-05-02T03:07:10Z
2015-01-06T11:39:51Z
2014-06-15T10:18:45Z
2015-02-25T19:27:52Z
2014-06-30T02:16:50Z
2014-07-02T14:42:26Z
2015-03-03T15:30:40Z
2014-09-12T03:36:00Z
2014-10-14T06:14:08Z
2014-05-13T08:43:17Z
2014-11-09T12:50:42Z
2014-11-23T04:22:10Z
2014-06-07T06:31:23Z
2015-02-07T22:08:11Z
2014-07-12T10:07:34Z
2015-02-07T07:04:41Z
2014-08-08T01:16:24Z
2014-06-23T07:52:56Z
2014-06-19T09:35:49Z
2014-06-06T17:12:43Z
2014-10-22T21:01:32Z
2014-05-04T20:14:09Z
2014-08-22T03:50:07Z
2014-04-05T20:25:08Z
2014-03-27T05:56:36Z
2014-05-12T18:34:04Z
2014-10-03T16:14:23Z
2014-06-08T17:22:18Z
2014-03-25T17:50:38Z
2014-04-08T07:49:37Z
2014-07-29T18:54:02Z
2015-03-03T15:19:45Z
2014-08-20T21:31:33Z
2014-11-24T18:12:27Z
2014-11-11T11:33:06Z
2014-11-30T06:03:03Z
2014-03-30T00:04:47Z
2014-12-20T12:30:47Z
2014-09-01T23:17:58Z
2014-07-26T20:28:32Z
2014-07-25T19:45:34Z
2015-01-31T10:13:03Z
2014-10-17T01:51:11Z
2014-11-03T05:09:00Z
2014-04-07T00:14:43Z
2014-11-26T13:09:46Z
2015-01-08T10:59:58Z
2014-11-03T22:41:44Z
2014-09-09T04:08:29Z
2015-01-31T23:35:02Z
2014-08-14T16:04:31Z
2014-08-22T19:16:26Z
2014-10-24T07:10:33Z
2014-08-07T00:02:48Z
2014-07-21T08:06:52Z
2014-05-27T13:26:45Z
2015-01-13T11:40:47Z
2014-04-30T23:05:06Z
2014-11-05T16:11:28Z
2014-06-04T03:20:47Z
2014-04-18T06:34:03Z
2014-05-30T06:57:38Z
2014-11-22T10:32:04Z
2014-12-31T09:28:41Z
2014-06-07T20:01:48Z
2014-09-06T19:39:51Z
2014-06-10T13:42:42Z
2014-04-23T15:00:45Z
2015-02-12T22:39:31Z
2015-02-09T14:50:22Z
2014-07-25T19:31:16Z
2014-06-02T17:02:02Z
2014-04-11T04:44:42Z
2014-06-09T12:01:59Z
2015-01-24T07:17:25Z
2014-12-13T00:31:52Z
2014-09-16T04:39:28Z
2014-03-16T03:17:36Z
2015-03-06T00:37:41Z
2015-01-16T08:50:26Z
2014-12-08T07:47:07Z
2014-06-06T03:41:59Z
2014-06-19T02:00:35Z
2015-03-10T11:39:06Z
2014-08-21T07:13:42Z
2015-02-12T22:23:56Z
2015-03-13T14:24:55Z
2014-08-07T02:33:09Z
2014-10-19T23:30:12Z
2014-06-08T20:46:14Z
2014-11-22T00:12:00Z
2014-11-16T23:56:15Z
2014-04-30T17:29:11Z
2014-10-17T01:34:16Z
2014-04-21T09:47:10Z
2014-04-18T16:14:59Z
2014-10-08T07:28:05Z
2014-07-08T22:15:54Z
2014-09-30T07:41:12Z
2014-10-08T21:22:17Z
2014-10-22T23:08:51Z
2015-02-22T10:55:53Z
2014-10-22T01:26:37Z
2014-11-08T06:31:02Z
2014-11-30T02:07:46Z
2014-08-14T20:30:29Z
2014-06-09T19:59:58Z
2015-01-19T14:04:32Z
2014-12-08T23:52:51Z
2014-11-04T17:51:07Z
2014-04-16T01:19:23Z
2014-04-03T09:53:36Z
2014-05-02T15:29:24Z
2015-01-02T01:59:17Z
2014-11-10T17:19:17Z
2015-02-17T01:46:19Z
2014-09-12T16:47:48Z
2014-05-10T19:37:31Z
2015-03-13T19:42:32Z
2014-09-17T08:09:31Z
2014-12-13T17:48:52Z
2014-08-17T18:23:33Z
2014-08-11T11:06:51Z
2015-02-07T11:02:35Z
2014-12-03T18:00:28Z
2014-07-30T13:39:53Z
2014-05-19T11:54:36Z
2014-11-19T15:48:41Z
2015-02-10T23:40:53Z
2014-11-08T00:19:22Z
2014-11-19T04:39:44Z
2014-05-24T03:19:12Z
2014-05-06T17:07:25Z
2014-07-12T23:01:05Z
2014-12-17T00:52:50Z
2015-02-09T04:03:19Z
2014-12-29T03:03:27Z
2014-10-29T20:44:36Z
2014-12-10T02:16:25Z
2015-01-24T03:29:28Z
2015-01-08T11:55:45Z
2014-12-12T16:38:33Z
2014-08-21T13:39:35Z
2014-12-19T22:07:15Z
2015-02-28T12:15:28Z
2014-05-28T14:28:24Z
2014-07-08T21:07:40Z
2014-11-04T09:14:52Z
2015-01-15T08:14:54Z
2014-06-28T14:51:13Z
2015-03-03T09:04:31Z
2015-02-18T05:14:38Z
2014-07-22T02:19:45Z
2014-09-11T12:58:13Z
2014-06-09T07:45:02Z
2014-07-29T07:02:07Z
2014-07-12T15:26:55Z
2014-07-07T03:29:10Z
2014-10-09T03:55:51Z
2014-11-30T04:09:30Z
2015-02-06T07:54:54Z
2014-03-27T14:38:03Z
2014-06-06T17:33:08Z
2014-09-28T06:57:46Z
2014-07-28T23:58:15Z
2014-08-05T09:08:43Z
2014-07-01T02:22:48Z
2014-04-01T14:48:52Z
2014-06-12T14:27:57Z
2014-12-10T02:24:34Z
2014-06-05T16:55:47Z
2014-10-19T23:58:37Z
2014-05-13T15:37:52Z
2014-04-10T12:50:13Z
2014-10-19T09:47:25Z
2014-05-19T23:39:11Z
2014-11-27T23:03:46Z
2014-11-09T10:02:36Z
2014-04-09T15:12:02Z
2014-04-28T15:09:07Z
2014-04-26T13:14:50Z
2014-08-02T12:34:39Z
2014-04-09T10:15:02Z
2015-01-23T19:48:28Z
2014-04-01T16:07:54Z
2014-05-24T02:34:20Z
2014-07-05T07:47:53Z
2014-10-27T02:40:14Z
2014-05-06T19:09:16Z
2015-02-12T02:44:51Z
2014-11-15T12:13:51Z
2014-04-08T05:53:13Z
2014-03-20T09:36:53Z
2014-09-22T04:45:24Z
2014-04-02T11:38:01Z
2014-12-08T19:49:04Z
2014-10-25T12:19:04Z
2015-03-11T04:40:04Z
2014-05-06T14:40:06Z
2014-12-05T18:51:16Z
2014-11-09T04:52:54Z
2014-12-12T00:32:27Z
2014-11-03T22:27:16Z
2015-01-08T00:43:24Z
2014-12-04T01:21:02Z
2014-05-13T15:25:57Z
2014-08-12T16:08:42Z
2014-10-25T18:43:37Z
2014-05-04T06:41:55Z
2014-05-01T18:50:45Z
2014-10-12T06:53:38Z
2015-01-13T20:12:40Z
2015-02-04T00:09:46Z
2014-06-16T17:06:33Z
2015-02-19T00:45:13Z
2014-05-20T12:35:09Z
2014-05-12T07:14:43Z
2014-08-26T20:19:52Z
2014-04-02T12:05:10Z
2014-04-23T13:42:58Z
2014-08-21T21:22:51Z
2014-11-18T01:58:40Z
2014-03-16T02:10:39Z
2014-06-17T02:42:04Z
2014-06-14T18:08:08Z
2014-11-04T07:34:32Z
2014-09-15T20:47:02Z
2015-03-08T21:21:44Z
2014-05-07T09:08:17Z
2014-07-24T21:52:04Z
2014-11-15T21:06:27Z
2015-01-02T19:44:27Z
2014-08-27T11:47:27Z
2015-02-10T12:25:40Z
2014-07-12T01:44:49Z
2014-12-28T13:49:01Z
2015-02-19T14:30:50Z
2014-08-26T05:54:53Z
2015-02-28T10:00:51Z
2015-02-22T03:51:08Z
2014-11-15T10:58:51Z
2014-10-10T22:53:22Z
2015-03-15T06:00:35Z
2014-09-23T01:22:55Z
2014-06-08T08:16:19Z
2014-05-11T16:04:41Z
2014-06-12T15:52:07Z
2015-02-03T10:24:16Z
2015-02-12T01:00:26Z
2014-11-05T06:30:44Z
2015-01-25T14:50:54Z
2014-12-01T18:56:41Z
2014-06-30T17:35:55Z
2015-02-17T01:13:17Z
2015-02-08T15:08:33Z
2014-09-26T08:18:12Z
2014-06-22T14:00:39Z
2014-08-18T07:00:11Z
2014-06-02T10:11:09Z
2014-12-03T06:12:36Z
2014-05-11T22:03:24Z
2014-03-26T02:12:01Z
2014-07-16T16:00:23Z
2014-03-17T09:26:32Z
2014-12-22T09:50:54Z
2015-01-09T07:38:55Z
2014-09-30T01:25:06Z
2014-07-24T15:51:43Z
2014-06-08T12:13:00Z
2014-05-19T05:09:55Z
2014-03-22T11:34:47Z
2014-08-27T16:18:37Z
2014-06-11T21:07:42Z
2014-09-02T22:30:14Z
2015-02-23T07:57:24Z
2014-03-16T05:39:00Z
2015-03-03T16:04:16Z
2015-03-09T22:38:19Z
2014-08-11T09:31:29Z
2014-12-31T16:12:28Z
2014-11-15T20:26:51Z
2014-08-01T02:36:51Z
2014-08-19T12:30:09Z
2014-10-04T08:15:14Z
2014-12-25T23:14:09Z
2014-08-31T16:47:00Z
2014-08-21T13:48:26Z
2014-06-30T18:24:23Z
2014-06-24T09:47:57Z
2014-05-16T19:18:11Z
2014-12-12T23:44:00Z
2014-08-11T21:01:55Z
2015-03-11T19:17:40Z
2014-11-11T13:39:04Z
2014-12-23T15:56:03Z
2014-06-25T14:06:25Z
2014-05-04T09:42:55Z
2014-09-28T18:19:43Z
2014-06-10T14:11:12Z
2014-06-02T16:27:10Z
2014-08-14T19:33:34Z
2014-12-19T18:32:22Z
2014-11-10T11:51:57Z
2014-04-03T22:55:28Z
2014-04-08T02:53:54Z
2014-09-11T14:42:12Z
2014-07-31T10:44:00Z
2014-12-17T02:33:35Z
2014-07-27T23:45:25Z
2014-04-14T12:50:06Z
2015-01-11T20:04:25Z
2014-05-23T21:07:02Z
2014-11-13T06:50:51Z
2014-09-28T05:41:19Z
2015-01-13T03:35:38Z
2014-09-04T14:35:53Z
2014-04-18T16:16:46Z
2014-11-30T13:45:09Z
2014-04-17T11:12:06Z
2014-07-14T22:57:07Z
2015-01-20T02:16:48Z
2015-01-09T21:58:31Z
2014-03-17T08:31:44Z
2014-09-17T16:54:27Z
2014-03-24T01:48:32Z
2014-06-13T21:12:32Z
2014-12-09T04:01:25Z
2014-06-21T10:58:13Z
2014-10-01T23:30:51Z
2014-07-18T17:47:16Z
2014-11-28T02:30:53Z
2014-04-01T18:24:50Z
2015-02-26T12:43:02Z
2014-06-14T01:58:21Z
2015-02-18T17:45:56Z
2014-04-11T23:13:32Z
2014-04-20T22:09:43Z
2015-01-25T06:00:28Z
2015-02-01T07:09:38Z
2014-12-07T19:31:53Z
2015-03-12T21:42:34Z
2014-09-13T08:31:07Z
2015-01-16T21:27:58Z
2014-12-30T00:47:52Z
2014-12-16T08:15:34Z
2014-04-21T21:28:53Z
2014-10-19T02:35:42Z
2014-05-26T13:52:36Z
2015-02-16T03:08:42Z
2014-07-18T20:38:28Z
2014-10-20T01:01:09Z
2015-02-27T03:57:47Z
2014-09-18T23:33:30Z
2014-12-12T10:33:44Z
2014-09-01T12:05:22Z
2014-06-16T23:26:33Z
2014-09-09T16:18:23Z
2014-12-07T17:04:36Z
2014-06-22T23:17:22Z
2014-09-24T13:59:41Z
2014-11-24T16:33:55Z
2014-11-24T16:35:45Z
2014-07-19T10:52:23Z
2014-05-15T08:12:28Z
2014-05-09T19:51:54Z
2014-12-20T15:47:39Z
2015-01-23T12:01:23Z
2014-05-14T01:06:52Z
2014-05-03T02:24:48Z
2014-12-29T17:01:23Z
2015-01-22T23:37:02Z
2014-10-03T09:18:01Z
2014-08-30T02:48:37Z
2014-07-28T00:39:00Z
2014-12-01T05:52:23Z
2015-03-08T07:32:14Z
2014-08-06T22:17:31Z
2015-02-02T22:38:45Z
2014-09-09T13:58:06Z
2014-06-03T21:55:06Z
2014-03-27T08:18:26Z
2014-06-17T22:13:52Z
2014-10-29T20:56:27Z
2014-08-03T04:42:43Z
2015-02-20T21:55:53Z
2014-06-04T17:36:03Z
2014-10-17T05:01:11Z
2014-08-28T13:31:09Z
2014-09-19T00:50:29Z
2014-10-22T23:11:59Z
2014-06-16T17:37:37Z
2014-08-17T15:05:18Z
2014-08-05T04:28:09Z
2014-09-02T06:16:31Z
2014-07-26T15:23:58Z
2015-02-21T10:53:48Z
2014-12-24T09:14:02Z
2014-10-24T12:27:56Z
2014-11-17T16:25:41Z
2014-07-01T12:27:59Z
2015-02-06T20:52:26Z
2014-10-20T17:17:34Z
2014-03-27T06:01:27Z
2015-02-14T02:47:13Z
2014-12-07T10:13:12Z
2015-02-22T05:05:13Z
2014-09-24T13:40:59Z
2014-10-02T00:43:35Z
2014-03-23T20:09:40Z
2014-05-17T01:15:03Z
2014-10-20T17:42:06Z
2014-08-02T21:04:13Z
2014-09-02T05:44:25Z
2014-10-02T16:53:12Z
2014-12-20T21:59:37Z
2014-07-09T10:14:28Z
2014-06-22T21:54:44Z
2014-12-21T17:47:18Z
2014-09-27T13:37:35Z
2014-09-18T03:59:49Z
2014-08-29T09:30:40Z
2015-03-09T16:04:32Z
2014-10-01T22:16:40Z
2014-06-16T08:01:08Z
2014-03-26T01:32:35Z
2014-07-01T05:32:37Z
2014-12-18T13:33:30Z
2015-03-11T14:21:07Z
2015-03-11T09:51:55Z
2014-10-27T04:28:28Z
2014-10-12T20:07:22Z
2014-09-22T05:03:54Z
2014-07-06T22:57:58Z
2014-12-04T22:14:43Z
2014-10-29T04:58:04Z
2015-01-04T16:36:24Z
2014-10-29T12:02:45Z
2014-03-26T05:57:58Z
2014-10-19T22:47:43Z
2014-07-30T08:57:57Z
2015-03-07T07:58:42Z
2014-11-28T03:05:16Z
2015-02-24T13:16:47Z
2014-06-04T07:25:59Z
2014-10-20T06:06:36Z
2014-03-23T15:59:57Z
2015-01-30T04:24:01Z
2015-03-05T14:54:05Z
2015-02-07T01:32:49Z
2014-06-06T03:01:51Z
2014-12-18T19:00:32Z
2014-08-25T10:30:47Z
2014-11-15T13:37:49Z
2015-03-01T15:16:34Z
2014-09-02T22:51:40Z
2014-12-12T13:41:15Z
2014-12-03T23:20:40Z
2014-10-10T16:25:53Z
2014-04-28T00:32:40Z
2014-10-10T15:21:56Z
2014-10-16T19:34:38Z
2014-09-03T02:33:45Z
2015-01-10T12:38:50Z
2014-08-05T03:33:40Z
2014-12-06T15:00:34Z
2014-04-27T15:46:38Z
2014-08-26T01:06:47Z
2015-02-26T03:41:40Z
2014-06-06T15:57:06Z
2014-11-15T04:38:28Z
2015-02-02T03:06:02Z
2014-09-23T06:23:27Z
2014-11-10T23:54:43Z
2014-06-21T22:23:38Z
2014-11-30T08:13:35Z
2014-06-08T20:31:44Z
2014-07-21T02:26:30Z
2014-07-06T15:59:46Z
2014-12-05T21:56:53Z
2014-07-10T00:01:26Z
2014-10-21T15:35:36Z
2014-04-04T10:05:00Z
2015-01-24T23:04:58Z
2014-07-20T04:54:07Z
2014-05-10T00:00:59Z
2014-09-12T18:24:39Z
2014-10-01T19:43:08Z
2014-05-11T00:56:20Z
2014-12-14T02:46:07Z
2015-03-05T02:27:26Z
2015-02-10T16:50:27Z
2014-11-13T00:47:45Z
2014-05-15T10:37:28Z
2014-06-17T07:48:23Z
2014-05-18T22:57:31Z
2014-08-10T15:37:55Z
2014-11-27T12:06:34Z
2014-07-10T07:19:32Z
2014-11-18T11:17:35Z
2014-05-06T14:37:37Z
2015-02-04T07:48:59Z
2014-07-24T01:52:15Z
2015-01-05T06:26:03Z
2015-01-28T22:52:37Z
2014-11-01T13:45:47Z
2014-07-14T22:38:24Z
2014-10-30T07:15:50Z
2014-11-24T22:04:10Z
2014-04-29T17:29:22Z
2014-05-10T22:43:26Z
2014-11-18T23:02:39Z
2014-11-26T15:45:25Z
2014-10-01T21:08:43Z
2015-03-12T17:21:57Z
@@ -0,0 +1,94 @@
jsmith@apache.org
someone@[216.109.118.76]
someone@yahoo.com
jsmith@apache.org
jsmith@apache.com
jsmith@apache.net
jsmith@apache.info
jsmith@apache.
jsmith@apache.c
someone@yahoo.museum
someone@yahoo.mu-seum
andy.noble@data-workshop.com
andy-noble@data-workshop.-com
andy-noble@data-workshop.c-om
andy-noble@data-workshop.co-m
andy.noble@data-workshop.com.
andy.noble@\u008fdata-workshop.com
andy.o'reilly@data-workshop.com
andy@o'reilly.data-workshop.com
foo+bar@i.am.not.in.us.example.com
foo+bar@example+3.com
test@%*.com
test@^&#.com
me@at&t.net
me@att.net
someone@-test.com
someone@test-.com
joe1234567890blow@apa,che.org
joe1234567890blow@apache.o,rg
joe1234567890blow@apache,org
joe1234567890blow @apache.org
joe1234567890blow@ apache.org
joe1234567890blow@apache.org
joe1234567890blow@apache.org
joe1234567890 blow@apache.org
joe1234567890blow@apa che.org
joe12345678901blow@apache.org
joe1234567890$blow@apache.org
joe1234567890-@apache.org
joe1234567890_@apache.org
joe1234567890+@apache.org
joe1234567890!@apache.org
joe1234567890*@apache.org
joe1234567890'@apache.org
joe1234567890%45@apache.org
joe1234567890?@apache.org
joe1234567890&@apache.org
joe1234567890=@apache.org
+joe1234567890@apache.org
!joe1234567890@apache.org
*joe1234567890@apache.org
'joe1234567890@apache.org
%joe123456789045@apache.org
?joe1234567890@apache.org
&joe1234567890@apache.org
=joe1234567890@apache.org
+@apache.org
!@apache.org
*@apache.org
'@apache.org
%@apache.org
?@apache.org
&@apache.org
=@apache.org
joe1234567890.@apache.org
.joe1234567890@apache.org
.@apache.org
joe1234567890.ok@apache.org
joe1234567890..ok@apache.org
..@apache.org
joe1234567890(@apache.org
joe1234567890)@apache.org
joe1234567890,@apache.org
joe1234567890;@apache.org
\"joe1234567890.\"@apache.org
\".joe1234567890\"@apache.org
\"joe1234567890+\"@apache.org
\"joe1234567890!\"@apache.org
\"joe1234567890*\"@apache.org
\"joe1234567890'\"@apache.org
\"joe1234567890(\"@apache.org
\"joe1234567890)\"@apache.org
\"joe1234567890,\"@apache.org
\"joe1234567890%45\"@apache.org
\"joe1234567890;\"@apache.org
\"joe1234567890?\"@apache.org
\"joe1234567890&\"@apache.org
\"joe1234567890=\"@apache.org
\"..\"@apache.org
abc-@abc.com
abc_@abc.com
abc-def@abc.com
abc_def@abc.com
abc@abc_def.com
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
import os
# 100 megabytes
LIMIT = 1024 * 1024 * 100
# read the small sample
with open('small', 'rb') as f:
small = f.read()
smallsize = len(small)
# copy-paste it enough times to the big file
total = 0
with open('big', 'wb') as f:
while total < LIMIT:
f.write(small)
total += smallsize
+101
View File
@@ -0,0 +1,101 @@
HEAD file://cwidoaajjb.pqzeztqtg.iagnuhmdq.npliaihmqn.yuptnwn/hlhkojvjvzmsgccwcpwhh/qfliekillmmdz/aypkwffmdojvpdodmrouzxuupqp/gjqnmbk/mnbtpocjbe/ttvqsflbsqirgahmutddqucg/nkycantossaikwulmgemuqttwx/foqeceoyiowyeftxpr/syjcvolygaguylfkx/gwgx?7B9Jq5CNzjzSFzJl7cCL4oUX HTTP/6.2
Content-Disposition: attachment; filename="fname.ext"
Content-Language: da
If-Match: "737060cd8c284d8af7ad3082f209582d"
If-None-Match: "737060cd8c284d8af7ad3082f209582d"
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Connection: Upgrade
X-Powered-By: PHP/5.4.0
Proxy-Authenticate: Basic
Warning: 199 Miscellaneous warning
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Retry-After: Fri, 07 Nov 2014 23:59:59 GMT
Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket
X-Att-Deviceid: GT-P7320/P7320XXLPG
Alt-Svc: http/1.1="http2.example.com:8001"; ma=7200
Accept-Ranges: bytes
Content-Language: da
Cache-Control: no-cache
Age: 12
Accept-Encoding: gzip, deflate
Content-Length: 51
WWW-Authenticate: Basic
Vary: *
Upgrade-Insecure-Requests: 1
Strict-Transport-Security: max-age=16070400; includeSubDomains
Public-Key-Pins: max-age=2592000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
Pragma: no-cache
Content-Length: 51
Host: en.wikipedia.org
X-Frame-Options: deny
POST https://hubgkuzz.qqwqvsfccy.psvyjbuva.afjqkipasn.zrdeeznzgo:7150/yfztaoqwaqlyuxfdkosgkegikcn/xme HTTP/6.6
Cache-Control: max-age=3600
Content-Length: 51
Content-Type: application/x-www-form-urlencoded
Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket
Alt-Svc: http/1.1="http2.example.com:8001"; ma=7200
Date: Tue, 15 Nov 1994 08:12:31 GMT
Accept-Charset: utf-8
Cookie: $Version=1; Skin=new;
X-Request-ID: f058ebd6-02f7-4d3f-942e-904344e8cde5
CONNECT zwusyxlehg.qxqjpqqjzq.rnrnmjbspj.ugbkvsriyw.gpchzrlqkk:8638 HTTP/7.4
Pragma: no-cache
Transfer-Encoding: chunked
Content-Location: /index.htm
X-Att-Deviceid: GT-P7320/P7320XXLPG
Public-Key-Pins: max-age=2592000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
Accept-Patch: text/example;charset=utf-8
Host: en.wikipedia.org:8080
X-Forwarded-For: client1, proxy1, proxy2
Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
DNT: 1 (Do Not Track Enabled)
X-UA-Compatible: Chrome=1
Tk: ?
Refresh: 5; url=http://www.w3.org/pub/WWW/People.html
X-UA-Compatible: IE=edge
Expect: 100-continue
DNT: 0 (Do Not Track Disabled)
WWW-Authenticate: Basic
Content-Type: application/x-www-form-urlencoded
Public-Key-Pins: max-age=2592000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-Content-Type-Options: nosniff
X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
X-Forwarded-Host: en.wikipedia.org
X-Att-Deviceid: GT-P7320/P7320XXLPG
Content-Location: /index.htm
Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT
HTTP/9.5 559 u
Date: Tue, 15 Nov 1994 08:12:31 GMT
Content-Length: 348
X-Forwarded-Proto: https
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Expires: Thu, 01 Dec 1994 16:00:00 GMT
WWW-Authenticate: Basic
Allow: GET, HEAD
Warning: 199 Miscellaneous warning
POST wllvzjwvpp.mhagladifk.joaq.rnprjmcpum.opadaxtssr HTTP/6.4
Warning: 199 Miscellaneous warning
Proxy-Authenticate: Basic
Content-Encoding: gzip
X-Forwarded-Host: en.wikipedia.org
Strict-Transport-Security: max-age=16070400; includeSubDomains
Content-Language: da
Allow: GET, HEAD
Retry-After: Fri, 07 Nov 2014 23:59:59 GMT
If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
X-Forwarded-For: client1, proxy1, proxy2
HTTP/0.6 463 2bs
From: user@example.com
X-Forwarded-Host: en.wikipedia.org
X-Forwarded-Host: en.wikipedia.org
X-UA-Compatible: IE=edge
X-UA-Compatible: IE=edge
Date: Tue, 15 Nov 1994 08:12:31 GMT
@@ -0,0 +1,9 @@
127.0.0.1
192.168.1.1
192.168.1.255
255.255.255.255
8.8.8.8
255.0.0.0
10.0.0.0
169.254.0.0
172.16.0.0
@@ -0,0 +1 @@
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaLine truncated
@@ -0,0 +1,19 @@
https://re2c.org
https://www.colm.net/open-source/ragel
https://github.com/diku-kmc/kleenexlang
https://github.com/skvadrik/re2c
https://arxiv.org/abs/1907.08837
https://laurikari.net/ville/spire2000-tnfa.pdf
https://www.semanticscholar.org/paper/Tagged-Deterministic-Finite-Automata-with-Lookahead-Trofimovich/3ca8101183d87580bc97dd7c1236d77bbd90a40d
http://re2c.org/2019_borsotti_trofimovich_efficient_posix_submatch_extraction_on_nfa.pdf
https://www.researchgate.net/publication/344781678_Efficient_POSIX_submatch_extraction_on_nondeterministic_finite_automata
https://kernel.org
https://en.wikipedia.org/
https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
http://190.102.237.163/jfymqrdxatqxxosr/eodoflhmefpbqunvzkwkxfgxj/ife/bbijkiueazcfwodgsddft/xpegxlfbdzafenjaqgjbnqrsb/poizlwooajtnejxpycftrcsfjkruln?DEVzXYliuaVThP2db4oE32q#fXoCDA1BJyjOUBJwpMOOC36Q7o6n
https://prlmszykmotajvhfingpy:5gJpVNFdVUCBumKIV0ciYat@tyekbzfzyn.kirctezfig.gvefopbqlf.onykhnytqd.uofiltbvdv/jiqe/odskecdswmouqaunyfuerpefcusuxa/fkqdmaueh/vzkskyxrpqkfzzjgujqmkt/qfnzplmxvunhvjq/kskwzjeueepwokxguatetegnjzgu/pysxiyoyssbfiibuonhk/wmzxsguoqoeutnkaanqqd/pkpbwvoepeutjbedkdimko/vogpbm#fBzuGdIV22C
file://ngngiosyeynlnyegckpwp:QoW1iBFx@171.234.221.207/ltdgogjynxrrnjygsltmcfihfsqfvk/mixerqujwbektqyzimadzdx/urb/vrvjsofccprkaavyyp/sycatuazj/vlmmmvozycmvpicrpcipfxywp/zddjtiahb
https://jqhvw:ssV@[4::a8:5ab]:7064/tto/xjdjuxhkqhuvmdbwn/kejaxevbfon/nxrvxlozfd/nefd/drhf/ya/meebpkpao/go/sv?XZtzUKrb4Qq19CsMmL
ftp://226.47.189.219/uttpjalgzirumdxcqstmop/rsavfunauwrnzbrbccv/qvnzgkypemnulagkcnxgmhg/vdzboggzuttu/wimrcceehdaznqnvguhi/hcmbkir/vxcincavxbheiuuqoukjsnd/rnkr/repqv/cdncqpiqhrughnlhbu?04HBSdquIv5jRN5POmtHr#t8TxSWH16brGRC79JCiBCp8bEyF
http:/laxn/rugglbrcb/znzlrhyoxapkznmedipktxhqzeohlw/rfmg/uyntiipnzdwjlfy/fktcgxrgcsfkr/rbbcxzybieozevucqxpmeq/apqyszyxgpq/zbknrolqhmtwjshockr/kicrlzsbtx?VbJp1VLkYC#mYPZplrVnb7UHSatrpGAwi
ftp://hukiuvtpzvmwmnxgomsujflyk:b1MSVh7pUWPjK24nnJoOOwKIET36s@6.119.196.62:5869/cyhsyhjykv#NlE8g3hz1Ebta8kk7LUvTm
+11
View File
@@ -0,0 +1,11 @@
set -ex
rm -rf kleenexlang
git clone --recursive https://github.com/diku-kmc/kleenexlang.git
cd kleenexlang
mkdir "install"
cabal build
cabal install --install-method=copy --installdir="$(pwd)/install"
cd ..
rm -f kexc
ln -s "kleenexlang/install/kexc" kexc
+16
View File
@@ -0,0 +1,16 @@
set -e
if [ -e ragel6 ] ; then
echo "ragel6 is already installed, quitting"
exit 0
fi
RAGEL_DIR=ragel-6.10
wget http://www.colm.net/files/ragel/"$RAGEL_DIR".tar.gz -O - | tar zx \
&& cd "$RAGEL_DIR" \
&& ./configure --prefix=$(pwd)/install \
&& make -j$(nproc) \
&& cd ..
ln -s "$RAGEL_DIR"/ragel/ragel ragel6
+31
View File
@@ -0,0 +1,31 @@
set -ex
if [ -e ragel7 ] ; then
echo "ragel7 is already installed, quitting"
exit 0
fi
COLM_DIR=colm-0.14.7
RAGEL_DIR=ragel-7.0.4
wget http://www.colm.net/files/colm/"$COLM_DIR".tar.gz -O - | tar zx \
&& cd "$COLM_DIR" \
&& sed -i 's|^#!/bin/bash|#!/usr/bin/env bash|' src/colm-wrap.sh \
&& ./configure \
--prefix=$(pwd)/install \
--disable-manual \
&& make -j$(nproc) \
&& make install \
&& cd ..
wget http://www.colm.net/files/ragel/"$RAGEL_DIR".tar.gz -O - | tar zx \
&& cd "$RAGEL_DIR" \
&& ./configure \
--prefix=$(pwd)/install \
--with-colm="$(pwd)/../$COLM_DIR/install" \
--disable-manual \
&& make -j$(nproc) \
&& make install \
&& cd ..
ln -s "$RAGEL_DIR"/install/bin/ragel ragel7
+22
View File
@@ -0,0 +1,22 @@
set -ex
if [ -e re2c3 ] ; then
echo "re2c3 is already installed, quitting"
exit 0
fi
RE2C_DIR=re2c-3.0
wget https://github.com/skvadrik/re2c/releases/download/3.0/re2c-3.0.tar.xz \
&& tar xf re2c-3.0.tar.xz \
&& rm re2c-3.0.tar.xz \
&& cd "$RE2C_DIR" \
&& ./configure \
--disable-golang \
--disable-rust \
--prefix=$(pwd)/install \
&& make -j$(nproc) \
&& make install \
&& cd ..
ln -s "$RE2C_DIR"/install/bin/re2c re2c3
@@ -0,0 +1,11 @@
ragel/21__cat2_4
ragel/22__cat2_8
ragel/24__cat4_2
ragel/25__cat4_4
ragel/28__cat8_2
ragel/33__rep_alt_5_3_2
ragel/34__rep_alt_13_11_7
ragel/35__rep_alt_23_19_17
ragel/36__rep_5_rep_3_rep_2
ragel/37__rep_13_rep_11_rep_7
ragel/38__rep_23_rep_19_rep_17
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,808 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xaagent: "
const buffer_unit_t const_1_0[9] = {0xa,0x61,0x67,0x65,0x6e,0x74,0x3a,0x20,0x22};
// \xaauthuser:
const buffer_unit_t const_1_1[11] = {0xa,0x61,0x75,0x74,0x68,0x75,0x73,0x65,0x72,0x3a,0x20};
// \xadate:
const buffer_unit_t const_1_2[7] = {0xa,0x64,0x61,0x74,0x65,0x3a,0x20};
// \xarequest:
const buffer_unit_t const_1_3[10] = {0xa,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x3a,0x20};
// \xasize:
const buffer_unit_t const_1_4[7] = {0xa,0x73,0x69,0x7a,0x65,0x3a,0x20};
// \xastatus:
const buffer_unit_t const_1_5[9] = {0xa,0x73,0x74,0x61,0x74,0x75,0x73,0x3a,0x20};
// \xaurl: "
const buffer_unit_t const_1_6[7] = {0xa,0x75,0x72,0x6c,0x3a,0x20,0x22};
// \xauserid:
const buffer_unit_t const_1_7[9] = {0xa,0x75,0x73,0x65,0x72,0x69,0x64,0x3a,0x20};
// "\xa\xa
const buffer_unit_t const_1_8[3] = {0x22,0xa,0xa};
// host:
const buffer_unit_t const_1_9[6] = {0x68,0x6f,0x73,0x74,0x3a,0x20};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/04__apache_log.kex\nSource md5: 5c2abee157 d 228b3e24d48c2163bfd\nSST states: 17\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && (((next[0] == '.') || (('0' <= next[0]) && (next[0] <= '9'))) && 1)))
{
outputarray(const_1_9,48);
outputconst(next[0],8);
consume(1);
goto l1_10;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == '"') && 1)))
{
outputarray(const_1_0,72);
consume(1);
goto l1_14;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == '"') && 1)))
{
outputarray(const_1_6,56);
consume(1);
goto l1_13;
}
goto fail1;
l1_3: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_3;
}
if (((avail >= 2) && ((next[0] == '-') && (((next[1] == 9) || (next[1] == ' ')) && 1))))
{
outputarray(const_1_4,56);
outputconst(next[0],8);
consume(2);
goto l1_2;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputarray(const_1_4,56);
outputconst(next[0],8);
consume(1);
goto l1_16;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputarray(const_1_5,72);
outputconst(next[0],8);
consume(1);
goto l1_15;
}
goto fail1;
l1_5: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_5;
}
if (((avail >= 2) && ((next[0] == '"') && ((((0 <= next[1]) && (next[1] <= 9)) || (((11 <= next[1]) && (next[1] <= '!')) || (('#' <= next[1]) && (next[1] <= 255)))) && 1))))
{
outputarray(const_1_3,80);
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
consume(2);
goto l1_12;
}
goto fail1;
l1_6: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_6;
}
if (((avail >= 2) && ((next[0] == '[') && ((((0 <= next[1]) && (next[1] <= 9)) || (((11 <= next[1]) && (next[1] <= 92)) || (('^' <= next[1]) && (next[1] <= 255)))) && 1))))
{
outputarray(const_1_2,56);
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
consume(2);
goto l1_11;
}
goto fail1;
l1_7: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_7;
}
if (((avail >= 2) && ((next[0] == '-') && (((next[1] == 9) || (next[1] == ' ')) && 1))))
{
outputarray(const_1_1,88);
outputconst(next[0],8);
consume(2);
goto l1_6;
}
goto fail1;
l1_8: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_8;
}
if (((avail >= 2) && ((next[0] == '-') && (((next[1] == 9) || (next[1] == ' ')) && 1))))
{
outputarray(const_1_7,72);
outputconst(next[0],8);
consume(2);
goto l1_7;
}
goto fail1;
l1_9: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && (((next[0] == '.') || (('0' <= next[0]) && (next[0] <= '9'))) && 1)))
{
outputarray(const_1_9,48);
outputconst(next[0],8);
consume(1);
goto l1_10;
}
goto fail1;
l1_10: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_8;
}
if (((avail >= 1) && (((next[0] == '.') || (('0' <= next[0]) && (next[0] <= '9'))) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_10;
}
goto fail1;
l1_11: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= 92)) || (('^' <= next[0]) && (next[0] <= 255)))) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_11;
}
if (((avail >= 2) && ((next[0] == ']') && (((next[1] == 9) || (next[1] == ' ')) && 1))))
{
outputconst(next[0],8);
consume(2);
goto l1_5;
}
goto fail1;
l1_12: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= '!')) || (('#' <= next[0]) && (next[0] <= 255)))) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_12;
}
if (((avail >= 2) && ((next[0] == '"') && (((next[1] == 9) || (next[1] == ' ')) && 1))))
{
outputconst(next[0],8);
consume(2);
goto l1_4;
}
goto fail1;
l1_13: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= '!')) || (('#' <= next[0]) && (next[0] <= 255)))) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_13;
}
if (((avail >= 2) && ((next[0] == '"') && (((next[1] == 9) || (next[1] == ' ')) && 1))))
{
outputconst(next[0],8);
consume(2);
goto l1_1;
}
goto fail1;
l1_14: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= '!')) || (('#' <= next[0]) && (next[0] <= 255)))) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_14;
}
if (((avail >= 2) && (cmp(&next[0],(unsigned char *) """\x22""""\xa""",2) && 1)))
{
outputarray(const_1_8,24);
consume(2);
goto l1_9;
}
goto fail1;
l1_15: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_15;
}
goto fail1;
l1_16: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == 9) || (next[0] == ' ')) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_16;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,793 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
buffer_t buf_1;
buffer_t buf_2;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// \xaday:
const buffer_unit_t const_1_1[6] = {0xa,0x64,0x61,0x79,0x3a,0x20};
// \xahours:
const buffer_unit_t const_1_2[8] = {0xa,0x68,0x6f,0x75,0x72,0x73,0x3a,0x20};
// \xaminutes:
const buffer_unit_t const_1_3[10] = {0xa,0x6d,0x69,0x6e,0x75,0x74,0x65,0x73,0x3a,0x20};
// \xamonth:
const buffer_unit_t const_1_4[8] = {0xa,0x6d,0x6f,0x6e,0x74,0x68,0x3a,0x20};
// \xaseconds:
const buffer_unit_t const_1_5[10] = {0xa,0x73,0x65,0x63,0x6f,0x6e,0x64,0x73,0x3a,0x20};
// \xatz:
const buffer_unit_t const_1_6[5] = {0xa,0x74,0x7a,0x3a,0x20};
// Z\xa
const buffer_unit_t const_1_7[2] = {0x5a,0xa};
// year:
const buffer_unit_t const_1_8[6] = {0x79,0x65,0x61,0x72,0x3a,0x20};
// year: 0
const buffer_unit_t const_1_9[7] = {0x79,0x65,0x61,0x72,0x3a,0x20,0x30};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/05__datetime.kex\nSource md5: c45f984dab5249fecb87 e76fa5b3c1f\nSST states: 13\n");
}
void init()
{
init_buffer(&buf_1);
init_buffer(&buf_2);
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '0') && 1)))
{
outputarray(const_1_9,56);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((('1' <= next[0]) && (next[0] <= '9')) && 1)))
{
reset(&buf_2);
reset(&buf_1);
outputarray(const_1_8,48);
outputconst(next[0],8);
consume(1);
goto l1_12;
}
goto fail1;
l1_1: if (!readnext(4, 4))
{
goto fail1;
}
if (((avail >= 4) && ((('0' <= next[0]) && (next[0] <= '9')) && ((('0' <= next[1]) && (next[1] <= '9')) && ((('0' <= next[2]) && (next[2] <= '9')) && ((next[3] == '-') && 1))))))
{
for(i = 0; i < 3; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_4,64);
consume(4);
goto l1_6;
}
goto fail1;
l1_2: if (!readnext(2, 2))
{
goto fail1;
}
if (((avail >= 2) && ((('0' <= next[0]) && (next[0] <= '5')) && ((('0' <= next[1]) && (next[1] <= '9')) && 1))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_6,40);
consume(2);
goto l1_10;
}
goto fail1;
l1_3: if (!readnext(3, 3))
{
goto fail1;
}
if (((avail >= 3) && ((('0' <= next[0]) && (next[0] <= '5')) && ((('0' <= next[1]) && (next[1] <= '9')) && ((next[2] == ':') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_5,80);
consume(3);
goto l1_2;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_11;
}
goto fail1;
l1_5: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 5) && ((('0' <= next[1]) && (next[1] <= '9')) && ((('0' <= next[2]) && (next[2] <= '9')) && ((('0' <= next[3]) && (next[3] <= '9')) && ((next[4] == '-') && 1))))))
{
for(i = 0; i < 4; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_4,64);
consume(5);
goto l1_6;
}
outputconst(next[0],8);
consume(1);
goto l1_5;
}
goto fail1;
l1_6: if (!readnext(3, 3))
{
goto fail1;
}
if (((avail >= 3) && ((next[0] == '0') && ((('1' <= next[1]) && (next[1] <= '9')) && ((next[2] == '-') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_1,48);
consume(3);
goto l1_7;
}
if (((avail >= 3) && ((next[0] == '1') && ((('0' <= next[1]) && (next[1] <= '2')) && ((next[2] == '-') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_1,48);
consume(3);
goto l1_7;
}
goto fail1;
l1_7: if (!readnext(3, 3))
{
goto fail1;
}
if (((avail >= 3) && ((next[0] == '0') && ((('1' <= next[1]) && (next[1] <= '9')) && ((next[2] == 'T') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_2,64);
consume(3);
goto l1_9;
}
if (((avail >= 3) && ((('1' <= next[0]) && (next[0] <= '2')) && ((('0' <= next[1]) && (next[1] <= '9')) && ((next[2] == 'T') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_2,64);
consume(3);
goto l1_9;
}
if (((avail >= 3) && ((next[0] == '3') && ((('0' <= next[1]) && (next[1] <= '1')) && ((next[2] == 'T') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_2,64);
consume(3);
goto l1_9;
}
goto fail1;
l1_8: if (!readnext(5, 5))
{
goto fail1;
}
if (((avail >= 5) && ((('0' <= next[0]) && (next[0] <= '1')) && ((('0' <= next[1]) && (next[1] <= '9')) && ((next[2] == ':') && ((('0' <= next[3]) && (next[3] <= '5')) && ((('0' <= next[4]) && (next[4] <= '9')) && 1)))))))
{
for(i = 0; i < 5; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_0,8);
consume(5);
goto l1_4;
}
if (((avail >= 5) && ((next[0] == '2') && ((('0' <= next[1]) && (next[1] <= '3')) && ((next[2] == ':') && ((('0' <= next[3]) && (next[3] <= '5')) && ((('0' <= next[4]) && (next[4] <= '9')) && 1)))))))
{
for(i = 0; i < 5; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_0,8);
consume(5);
goto l1_4;
}
goto fail1;
l1_9: if (!readnext(3, 3))
{
goto fail1;
}
if (((avail >= 3) && ((('0' <= next[0]) && (next[0] <= '1')) && ((('0' <= next[1]) && (next[1] <= '9')) && ((next[2] == ':') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_3,80);
consume(3);
goto l1_3;
}
if (((avail >= 3) && ((next[0] == '2') && ((('0' <= next[1]) && (next[1] <= '3')) && ((next[2] == ':') && 1)))))
{
for(i = 0; i < 2; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_3,80);
consume(3);
goto l1_3;
}
goto fail1;
l1_10: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && (((next[0] == '+') || (next[0] == '-')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_8;
}
if (((avail >= 1) && ((next[0] == 'Z') && 1)))
{
outputarray(const_1_7,16);
consume(1);
goto l1_4;
}
goto fail1;
l1_11: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == '0') && 1)))
{
outputarray(const_1_9,56);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((('1' <= next[0]) && (next[0] <= '9')) && 1)))
{
reset(&buf_2);
append(&buf_2,next[0],8);
reset(&buf_1);
append(&buf_1,next[0],8);
outputarray(const_1_8,48);
consume(1);
goto l1_12;
}
goto fail1;
l1_12: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 3) && ((('0' <= next[1]) && (next[1] <= '9')) && ((('0' <= next[2]) && (next[2] <= '9')) && 1))))
{
if (((avail >= 4) && ((next[3] == '-') && 1)))
{
output(&buf_2);
for(i = 0; i < 3; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_4,64);
consume(4);
goto l1_6;
}
if (((avail >= 5) && ((('0' <= next[3]) && (next[3] <= '9')) && ((next[4] == '-') && 1))))
{
output(&buf_1);
for(i = 0; i < 4; i++)
{ outputconst(next[0 + i],8);
}
outputarray(const_1_4,64);
consume(5);
goto l1_6;
}
}
output(&buf_1);
outputconst(next[0],8);
consume(1);
goto l1_5;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,882 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
buffer_t buf_1;
buffer_t buf_2;
buffer_t buf_3;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
//
const buffer_unit_t const_1_1[1] = {0x20};
// -
const buffer_unit_t const_1_2[1] = {0x2d};
// .
const buffer_unit_t const_1_3[1] = {0x2e};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/06__email.kex\nSource md5: 437ac440bbbfc56a11b3965ce24849 0\nSST states: 11\n");
}
void init()
{
init_buffer(&buf_1);
init_buffer(&buf_2);
init_buffer(&buf_3);
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ' ')) || ((next[0] == '"') || ((('(' <= next[0]) && (next[0] <= ')')) || ((next[0] == ',') || ((next[0] == '.') || (((':' <= next[0]) && (next[0] <= '<')) || ((next[0] == '>') || ((('@' <= next[0]) && (next[0] <= ']')) || ((127 <= next[0]) && (next[0] <= 255))))))))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && (((next[0] == '!') || ((('#' <= next[0]) && (next[0] <= 39)) || ((('*' <= next[0]) && (next[0] <= '+')) || ((next[0] == '-') || ((('/' <= next[0]) && (next[0] <= '9')) || ((next[0] == '=') || ((next[0] == '?') || (('^' <= next[0]) && (next[0] <= '~'))))))))) && 1)))
{
reset(&buf_1);
appendarray(&buf_1,const_1_1,8);
append(&buf_1,next[0],8);
consume(1);
goto l1_3;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= '/')) || (((':' <= next[0]) && (next[0] <= '`')) || (('{' <= next[0]) && (next[0] <= 255))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && (((('0' <= next[0]) && (next[0] <= '9')) || (('a' <= next[0]) && (next[0] <= 'z'))) && 1)))
{
append(&buf_1,next[0],8);
consume(1);
goto l1_8;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || ((11 <= next[0]) && (next[0] <= 255))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
goto fail1;
l1_3: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ' ')) || ((next[0] == '"') || ((('(' <= next[0]) && (next[0] <= ')')) || ((next[0] == ',') || (((':' <= next[0]) && (next[0] <= '<')) || ((next[0] == '>') || ((('A' <= next[0]) && (next[0] <= ']')) || ((127 <= next[0]) && (next[0] <= 255)))))))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && (((next[0] == '!') || ((('#' <= next[0]) && (next[0] <= 39)) || ((('*' <= next[0]) && (next[0] <= '+')) || ((next[0] == '-') || ((('/' <= next[0]) && (next[0] <= '9')) || ((next[0] == '=') || ((next[0] == '?') || (('^' <= next[0]) && (next[0] <= '~'))))))))) && 1)))
{
append(&buf_1,next[0],8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
if (((avail >= 2) && (((next[1] == '!') || ((('#' <= next[1]) && (next[1] <= 39)) || ((('*' <= next[1]) && (next[1] <= '+')) || ((next[1] == '-') || ((('/' <= next[1]) && (next[1] <= '9')) || ((next[1] == '=') || ((next[1] == '?') || (('^' <= next[1]) && (next[1] <= '~'))))))))) && 1)))
{
for(i = 0; i < 2; i++)
{ append(&buf_1,next[0 + i],8);
}
consume(2);
goto l1_5;
}
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == '@') && 1)))
{
appendarray(&buf_1,const_1_1,8);
consume(1);
goto l1_1;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ' ')) || ((next[0] == '"') || ((('(' <= next[0]) && (next[0] <= ')')) || ((next[0] == ',') || ((next[0] == '.') || (((':' <= next[0]) && (next[0] <= '<')) || ((next[0] == '>') || ((('@' <= next[0]) && (next[0] <= ']')) || ((127 <= next[0]) && (next[0] <= 255))))))))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && (((next[0] == '!') || ((('#' <= next[0]) && (next[0] <= 39)) || ((('*' <= next[0]) && (next[0] <= '+')) || ((next[0] == '-') || ((('/' <= next[0]) && (next[0] <= '9')) || ((next[0] == '=') || ((next[0] == '?') || (('^' <= next[0]) && (next[0] <= '~'))))))))) && 1)))
{
reset(&buf_1);
appendarray(&buf_1,const_1_1,8);
append(&buf_1,next[0],8);
consume(1);
goto l1_3;
}
goto fail1;
l1_5: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ' ')) || ((next[0] == '"') || ((('(' <= next[0]) && (next[0] <= ')')) || ((next[0] == ',') || (((':' <= next[0]) && (next[0] <= '<')) || ((next[0] == '>') || ((('A' <= next[0]) && (next[0] <= ']')) || ((127 <= next[0]) && (next[0] <= 255)))))))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && (((next[0] == '!') || ((('#' <= next[0]) && (next[0] <= 39)) || ((('*' <= next[0]) && (next[0] <= '+')) || ((next[0] == '-') || ((('/' <= next[0]) && (next[0] <= '9')) || ((next[0] == '=') || ((next[0] == '?') || (('^' <= next[0]) && (next[0] <= '~'))))))))) && 1)))
{
append(&buf_1,next[0],8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
if (((avail >= 2) && (((next[1] == '!') || ((('#' <= next[1]) && (next[1] <= 39)) || ((('*' <= next[1]) && (next[1] <= '+')) || ((next[1] == '-') || ((('/' <= next[1]) && (next[1] <= '9')) || ((next[1] == '=') || ((next[1] == '?') || (('^' <= next[1]) && (next[1] <= '~'))))))))) && 1)))
{
for(i = 0; i < 2; i++)
{ append(&buf_1,next[0 + i],8);
}
consume(2);
goto l1_5;
}
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == '@') && 1)))
{
appendarray(&buf_1,const_1_1,8);
consume(1);
goto l1_1;
}
goto fail1;
l1_6: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= '/')) || (((':' <= next[0]) && (next[0] <= '`')) || (('{' <= next[0]) && (next[0] <= 255))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && (((('0' <= next[0]) && (next[0] <= '9')) || (('a' <= next[0]) && (next[0] <= 'z'))) && 1)))
{
reset(&buf_3);
append(&buf_3,next[0],8);
reset(&buf_2);
append(&buf_2,next[0],8);
consume(1);
goto l1_10;
}
goto fail1;
l1_7: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ',')) || ((('.' <= next[0]) && (next[0] <= '/')) || (((':' <= next[0]) && (next[0] <= '`')) || (('{' <= next[0]) && (next[0] <= 255)))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == '-') && 1)))
{
appendarray(&buf_1,const_1_2,8);
consume(1);
goto l1_7;
}
if (((avail >= 1) && (((('0' <= next[0]) && (next[0] <= '9')) || (('a' <= next[0]) && (next[0] <= 'z'))) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
for(i = 0; i < 2; i++)
{ append(&buf_1,next[0 + i],8);
}
consume(2);
goto l1_6;
}
append(&buf_1,next[0],8);
consume(1);
goto l1_7;
}
goto fail1;
l1_8: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ',')) || ((next[0] == '/') || (((':' <= next[0]) && (next[0] <= '`')) || (('{' <= next[0]) && (next[0] <= 255)))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == '-') && 1)))
{
appendarray(&buf_1,const_1_2,8);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
appendarray(&buf_1,const_1_3,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && (((('0' <= next[0]) && (next[0] <= '9')) || (('a' <= next[0]) && (next[0] <= 'z'))) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
for(i = 0; i < 2; i++)
{ append(&buf_1,next[0 + i],8);
}
consume(2);
goto l1_6;
}
append(&buf_1,next[0],8);
consume(1);
goto l1_7;
}
goto fail1;
l1_9: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ',')) || ((('.' <= next[0]) && (next[0] <= '/')) || (((':' <= next[0]) && (next[0] <= '`')) || (('{' <= next[0]) && (next[0] <= 255)))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == '-') && 1)))
{
appendarray(&buf_3,const_1_2,8);
appendarray(&buf_2,const_1_2,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && (((('0' <= next[0]) && (next[0] <= '9')) || (('a' <= next[0]) && (next[0] <= 'z'))) && 1)))
{
if (((avail >= 2) && ((next[1] == 10) && 1)))
{
output(&buf_1);
output(&buf_3);
outputconst(next[0],8);
outputarray(const_1_0,8);
consume(2);
goto l1_4;
}
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
concat(&buf_1,&buf_2);
for(i = 0; i < 2; i++)
{ append(&buf_1,next[0 + i],8);
}
consume(2);
goto l1_6;
}
append(&buf_3,next[0],8);
append(&buf_2,next[0],8);
consume(1);
goto l1_9;
}
goto fail1;
l1_10: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((((0 <= next[0]) && (next[0] <= 9)) || (((11 <= next[0]) && (next[0] <= ',')) || ((next[0] == '/') || (((':' <= next[0]) && (next[0] <= '`')) || (('{' <= next[0]) && (next[0] <= 255)))))) && 1)))
{
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
output(&buf_3);
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == '-') && 1)))
{
appendarray(&buf_3,const_1_2,8);
appendarray(&buf_2,const_1_2,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
concat(&buf_1,&buf_2);
appendarray(&buf_1,const_1_3,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && (((('0' <= next[0]) && (next[0] <= '9')) || (('a' <= next[0]) && (next[0] <= 'z'))) && 1)))
{
if (((avail >= 2) && ((next[1] == 10) && 1)))
{
output(&buf_1);
output(&buf_3);
outputconst(next[0],8);
outputarray(const_1_0,8);
consume(2);
goto l1_4;
}
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
concat(&buf_1,&buf_2);
for(i = 0; i < 2; i++)
{ append(&buf_1,next[0 + i],8);
}
consume(2);
goto l1_6;
}
append(&buf_3,next[0],8);
append(&buf_2,next[0],8);
consume(1);
goto l1_9;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,826 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// ,
const buffer_unit_t const_1_1[1] = {0x2c};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/07__ipv4.kex\nSource md5: c1c35f349c1fef94586727bc137db489\nSST states: 17\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_8;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_5;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_6;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_7;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
outputconst(next[0],8);
consume(1);
goto l1_8;
}
goto fail1;
l1_5: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == 10) && 1)))
{
outputconst(next[0],8);
outputarray(const_1_0,8);
consume(2);
goto l1_4;
}
outputconst(next[0],8);
consume(1);
goto l1_9;
}
goto fail1;
l1_6: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_1;
}
outputconst(next[0],8);
consume(1);
goto l1_10;
}
goto fail1;
l1_7: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_2;
}
outputconst(next[0],8);
consume(1);
goto l1_11;
}
goto fail1;
l1_8: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_3;
}
outputconst(next[0],8);
consume(1);
goto l1_12;
}
goto fail1;
l1_9: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == 10) && 1)))
{
outputconst(next[0],8);
outputarray(const_1_0,8);
consume(2);
goto l1_4;
}
outputconst(next[0],8);
consume(1);
goto l1_13;
}
goto fail1;
l1_10: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_1;
}
outputconst(next[0],8);
consume(1);
goto l1_14;
}
goto fail1;
l1_11: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_2;
}
outputconst(next[0],8);
consume(1);
goto l1_15;
}
goto fail1;
l1_12: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((('0' <= next[0]) && (next[0] <= '9')) && 1)))
{
if (((avail >= 2) && ((next[1] == '.') && 1)))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_3;
}
outputconst(next[0],8);
consume(1);
goto l1_16;
}
goto fail1;
l1_13: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 2) && ((('0' <= next[0]) && (next[0] <= '9')) && ((next[1] == 10) && 1))))
{
outputconst(next[0],8);
outputarray(const_1_0,8);
consume(2);
goto l1_4;
}
goto fail1;
l1_14: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_1;
}
if (((avail >= 2) && ((('0' <= next[0]) && (next[0] <= '9')) && ((next[1] == '.') && 1))))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_1;
}
goto fail1;
l1_15: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_2;
}
if (((avail >= 2) && ((('0' <= next[0]) && (next[0] <= '9')) && ((next[1] == '.') && 1))))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_2;
}
goto fail1;
l1_16: if (!readnext(1, 2))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == '.') && 1)))
{
outputarray(const_1_1,8);
consume(1);
goto l1_3;
}
if (((avail >= 2) && ((('0' <= next[0]) && (next[0] <= '9')) && ((next[1] == '.') && 1))))
{
outputconst(next[0],8);
outputarray(const_1_1,8);
consume(2);
goto l1_3;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,595 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// A\xa
const buffer_unit_t const_1_1[2] = {0x41,0xa};
// Aa
const buffer_unit_t const_1_2[2] = {0x41,0x61};
// Bb
const buffer_unit_t const_1_3[2] = {0x42,0x62};
// a
const buffer_unit_t const_1_4[1] = {0x61};
// b
const buffer_unit_t const_1_5[1] = {0x62};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/10__alt1_2.kex\nSource md5: 933017c27ef6b9d9873167f64a593afc\nSST states: 4\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_2,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_3,16);
consume(1);
goto l1_2;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_4,8);
consume(1);
goto l1_1;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_5,8);
consume(1);
goto l1_2;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_2,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_3,16);
consume(1);
goto l1_2;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,661 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// A\xa
const buffer_unit_t const_1_1[2] = {0x41,0xa};
// Aa
const buffer_unit_t const_1_2[2] = {0x41,0x61};
// Bb
const buffer_unit_t const_1_3[2] = {0x42,0x62};
// Cc
const buffer_unit_t const_1_4[2] = {0x43,0x63};
// Dd
const buffer_unit_t const_1_5[2] = {0x44,0x64};
// a
const buffer_unit_t const_1_6[1] = {0x61};
// b
const buffer_unit_t const_1_7[1] = {0x62};
// c
const buffer_unit_t const_1_8[1] = {0x63};
// d
const buffer_unit_t const_1_9[1] = {0x64};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/11__alt1_4.kex\nSource md5: a46aa0b6cb7b64dabc59 919 e23de80\nSST states: 6\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_2,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_3,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_4;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_1;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_7,8);
consume(1);
goto l1_2;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_8,8);
consume(1);
goto l1_3;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_9,8);
consume(1);
goto l1_4;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_2,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_3,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_4;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,793 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// A\xa
const buffer_unit_t const_1_1[2] = {0x41,0xa};
// Aa
const buffer_unit_t const_1_2[2] = {0x41,0x61};
// Bb
const buffer_unit_t const_1_3[2] = {0x42,0x62};
// Cc
const buffer_unit_t const_1_4[2] = {0x43,0x63};
// Dd
const buffer_unit_t const_1_5[2] = {0x44,0x64};
// Ee
const buffer_unit_t const_1_6[2] = {0x45,0x65};
// Ff
const buffer_unit_t const_1_7[2] = {0x46,0x66};
// Gg
const buffer_unit_t const_1_8[2] = {0x47,0x67};
// Hh
const buffer_unit_t const_1_9[2] = {0x48,0x68};
// a
const buffer_unit_t const_1_10[1] = {0x61};
// b
const buffer_unit_t const_1_11[1] = {0x62};
// c
const buffer_unit_t const_1_12[1] = {0x63};
// d
const buffer_unit_t const_1_13[1] = {0x64};
// e
const buffer_unit_t const_1_14[1] = {0x65};
// f
const buffer_unit_t const_1_15[1] = {0x66};
// g
const buffer_unit_t const_1_16[1] = {0x67};
// h
const buffer_unit_t const_1_17[1] = {0x68};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/12__alt1_8.kex\nSource md5: ba40f7ea 99c54e73bc1dee39826 aef\nSST states: 10\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_2,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_3,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'e') && 1)))
{
outputarray(const_1_6,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'f') && 1)))
{
outputarray(const_1_7,16);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'g') && 1)))
{
outputarray(const_1_8,16);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'h') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_8;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_1;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_11,8);
consume(1);
goto l1_2;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_12,8);
consume(1);
goto l1_3;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_13,8);
consume(1);
goto l1_4;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'e') && 1)))
{
outputarray(const_1_14,8);
consume(1);
goto l1_5;
}
goto fail1;
l1_6: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'f') && 1)))
{
outputarray(const_1_15,8);
consume(1);
goto l1_6;
}
goto fail1;
l1_7: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'g') && 1)))
{
outputarray(const_1_16,8);
consume(1);
goto l1_7;
}
goto fail1;
l1_8: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'h') && 1)))
{
outputarray(const_1_17,8);
consume(1);
goto l1_8;
}
goto fail1;
l1_9: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_2,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_3,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'e') && 1)))
{
outputarray(const_1_6,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'f') && 1)))
{
outputarray(const_1_7,16);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'g') && 1)))
{
outputarray(const_1_8,16);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'h') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_8;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,657 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
buffer_t buf_1;
buffer_t buf_2;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// A\xa
const buffer_unit_t const_1_1[2] = {0x41,0xa};
// AA\xa
const buffer_unit_t const_1_2[3] = {0x41,0x41,0xa};
// ABb
const buffer_unit_t const_1_3[3] = {0x41,0x42,0x62};
// Aa
const buffer_unit_t const_1_4[2] = {0x41,0x61};
// Bb
const buffer_unit_t const_1_5[2] = {0x42,0x62};
// a
const buffer_unit_t const_1_6[1] = {0x61};
// b
const buffer_unit_t const_1_7[1] = {0x62};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/13__alt2_2.kex\nSource md5: 8e558b 4654ac181234bab147e994f1d\nSST states: 6\n");
}
void init()
{
init_buffer(&buf_1);
init_buffer(&buf_2);
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_5,16);
reset(&buf_1);
appendarray(&buf_1,const_1_3,24);
consume(1);
goto l1_4;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_3;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_2;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_7,8);
consume(1);
goto l1_3;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
output(&buf_2);
outputarray(const_1_4,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
appendarray(&buf_2,const_1_7,8);
appendarray(&buf_1,const_1_7,8);
consume(1);
goto l1_4;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_5,16);
reset(&buf_1);
appendarray(&buf_1,const_1_3,24);
consume(1);
goto l1_4;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,845 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
buffer_t buf_1;
buffer_t buf_2;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// A\xa
const buffer_unit_t const_1_1[2] = {0x41,0xa};
// AA\xa
const buffer_unit_t const_1_2[3] = {0x41,0x41,0xa};
// ABb
const buffer_unit_t const_1_3[3] = {0x41,0x42,0x62};
// ACc
const buffer_unit_t const_1_4[3] = {0x41,0x43,0x63};
// ADd
const buffer_unit_t const_1_5[3] = {0x41,0x44,0x64};
// Aa
const buffer_unit_t const_1_6[2] = {0x41,0x61};
// Bb
const buffer_unit_t const_1_7[2] = {0x42,0x62};
// Cc
const buffer_unit_t const_1_8[2] = {0x43,0x63};
// Dd
const buffer_unit_t const_1_9[2] = {0x44,0x64};
// a
const buffer_unit_t const_1_10[1] = {0x61};
// b
const buffer_unit_t const_1_11[1] = {0x62};
// c
const buffer_unit_t const_1_12[1] = {0x63};
// d
const buffer_unit_t const_1_13[1] = {0x64};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/14__alt2_4.kex\nSource md5: a7516a1d89d83c9d3ebcb1332232 4b6\nSST states: 10\n");
}
void init()
{
init_buffer(&buf_1);
init_buffer(&buf_2);
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_7,16);
reset(&buf_1);
appendarray(&buf_1,const_1_3,24);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_8,16);
reset(&buf_1);
appendarray(&buf_1,const_1_4,24);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_9,16);
reset(&buf_1);
appendarray(&buf_1,const_1_5,24);
consume(1);
goto l1_8;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_7,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_8,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_5;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_2;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_11,8);
consume(1);
goto l1_3;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
outputarray(const_1_12,8);
consume(1);
goto l1_4;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
outputarray(const_1_13,8);
consume(1);
goto l1_5;
}
goto fail1;
l1_6: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
output(&buf_2);
outputarray(const_1_6,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
appendarray(&buf_2,const_1_11,8);
appendarray(&buf_1,const_1_11,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
output(&buf_2);
outputarray(const_1_8,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
output(&buf_2);
outputarray(const_1_9,16);
consume(1);
goto l1_5;
}
goto fail1;
l1_7: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
output(&buf_2);
outputarray(const_1_6,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
output(&buf_2);
outputarray(const_1_7,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
appendarray(&buf_2,const_1_12,8);
appendarray(&buf_1,const_1_12,8);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
output(&buf_2);
outputarray(const_1_9,16);
consume(1);
goto l1_5;
}
goto fail1;
l1_8: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
output(&buf_2);
outputarray(const_1_6,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
output(&buf_2);
outputarray(const_1_7,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
output(&buf_2);
outputarray(const_1_8,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
appendarray(&buf_2,const_1_13,8);
appendarray(&buf_1,const_1_13,8);
consume(1);
goto l1_8;
}
goto fail1;
l1_9: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_7,16);
reset(&buf_1);
appendarray(&buf_1,const_1_3,24);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'c') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_8,16);
reset(&buf_1);
appendarray(&buf_1,const_1_4,24);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'd') && 1)))
{
reset(&buf_2);
appendarray(&buf_2,const_1_9,16);
reset(&buf_1);
appendarray(&buf_1,const_1_5,24);
consume(1);
goto l1_8;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,803 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
buffer_t buf_1;
buffer_t buf_2;
buffer_t buf_3;
buffer_t buf_4;
buffer_t buf_5;
buffer_t buf_6;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// A
const buffer_unit_t const_1_1[1] = {0x41};
// AA
const buffer_unit_t const_1_2[2] = {0x41,0x41};
// AAA\xa
const buffer_unit_t const_1_3[4] = {0x41,0x41,0x41,0xa};
// AAAA\xa
const buffer_unit_t const_1_4[5] = {0x41,0x41,0x41,0x41,0xa};
// ABb
const buffer_unit_t const_1_5[3] = {0x41,0x42,0x62};
// Aa
const buffer_unit_t const_1_6[2] = {0x41,0x61};
// Bb
const buffer_unit_t const_1_7[2] = {0x42,0x62};
// a
const buffer_unit_t const_1_8[1] = {0x61};
// b
const buffer_unit_t const_1_9[1] = {0x62};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/16__alt4_2.kex\nSource md5: 1216b4916935f0 0a1284315ccc3d519\nSST states: 10\n");
}
void init()
{
init_buffer(&buf_1);
init_buffer(&buf_2);
init_buffer(&buf_3);
init_buffer(&buf_4);
init_buffer(&buf_5);
init_buffer(&buf_6);
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_4,40);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_6);
appendarray(&buf_6,const_1_7,16);
reset(&buf_5);
appendarray(&buf_5,const_1_7,16);
reset(&buf_4);
appendarray(&buf_4,const_1_7,16);
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
consume(1);
goto l1_9;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_3,32);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_8,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_5);
appendarray(&buf_5,const_1_7,16);
reset(&buf_4);
appendarray(&buf_4,const_1_7,16);
reset(&buf_2);
appendarray(&buf_2,const_1_5,24);
consume(1);
goto l1_8;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_8,8);
consume(1);
goto l1_2;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,8);
consume(1);
goto l1_3;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
appendarray(&buf_4,const_1_8,8);
appendarray(&buf_1,const_1_8,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
output(&buf_4);
outputarray(const_1_7,16);
consume(1);
goto l1_3;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
output(&buf_4);
outputarray(const_1_6,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
appendarray(&buf_4,const_1_9,8);
appendarray(&buf_1,const_1_9,8);
consume(1);
goto l1_5;
}
goto fail1;
l1_6: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_4,40);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,16);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
reset(&buf_6);
appendarray(&buf_6,const_1_7,16);
reset(&buf_5);
appendarray(&buf_5,const_1_7,16);
reset(&buf_4);
appendarray(&buf_4,const_1_7,16);
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
consume(1);
goto l1_9;
}
goto fail1;
l1_7: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,8);
output(&buf_2);
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
appendarray(&buf_5,const_1_8,8);
appendarray(&buf_4,const_1_8,8);
appendarray(&buf_2,const_1_8,8);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
appendarray(&buf_4,const_1_7,16);
reset(&buf_1);
appendarray(&buf_1,const_1_1,8);
concat(&buf_1,&buf_5);
appendarray(&buf_1,const_1_7,16);
consume(1);
goto l1_5;
}
goto fail1;
l1_8: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,8);
output(&buf_2);
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
appendarray(&buf_4,const_1_6,16);
reset(&buf_1);
appendarray(&buf_1,const_1_1,8);
concat(&buf_1,&buf_5);
appendarray(&buf_1,const_1_6,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
appendarray(&buf_5,const_1_9,8);
appendarray(&buf_4,const_1_9,8);
appendarray(&buf_2,const_1_9,8);
consume(1);
goto l1_8;
}
goto fail1;
l1_9: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,16);
output(&buf_3);
outputarray(const_1_0,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
appendarray(&buf_5,const_1_6,16);
appendarray(&buf_4,const_1_6,16);
reset(&buf_2);
appendarray(&buf_2,const_1_1,8);
concat(&buf_2,&buf_6);
appendarray(&buf_2,const_1_6,16);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
appendarray(&buf_6,const_1_9,8);
appendarray(&buf_5,const_1_9,8);
appendarray(&buf_4,const_1_9,8);
appendarray(&buf_3,const_1_9,8);
consume(1);
goto l1_9;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,651 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// .\xa
const buffer_unit_t const_1_1[2] = {0x2e,0xa};
// ..\xa
const buffer_unit_t const_1_2[3] = {0x2e,0x2e,0xa};
// ...\xa
const buffer_unit_t const_1_3[4] = {0x2e,0x2e,0x2e,0xa};
// .a
const buffer_unit_t const_1_4[2] = {0x2e,0x61};
// .b
const buffer_unit_t const_1_5[2] = {0x2e,0x62};
// a
const buffer_unit_t const_1_6[1] = {0x61};
// b
const buffer_unit_t const_1_7[1] = {0x62};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/20__cat2_0.kex\nSource md5: 2a1c6fa6b7682bb74d 0bddd4dcf7a51\nSST states: 6\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_3,32);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_3;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_3,32);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_3;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_4;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_4,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_7,8);
consume(1);
goto l1_3;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_7,8);
consume(1);
goto l1_4;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_3,32);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_6,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_5,16);
consume(1);
goto l1_3;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,751 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// .\xa
const buffer_unit_t const_1_1[2] = {0x2e,0xa};
// ..\xa
const buffer_unit_t const_1_2[3] = {0x2e,0x2e,0xa};
// ...\xa
const buffer_unit_t const_1_3[4] = {0x2e,0x2e,0x2e,0xa};
// ....\xa
const buffer_unit_t const_1_4[5] = {0x2e,0x2e,0x2e,0x2e,0xa};
// .....\xa
const buffer_unit_t const_1_5[6] = {0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ......\xa
const buffer_unit_t const_1_6[7] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// .......\xa
const buffer_unit_t const_1_7[8] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// .a
const buffer_unit_t const_1_8[2] = {0x2e,0x61};
// .b
const buffer_unit_t const_1_9[2] = {0x2e,0x62};
// a
const buffer_unit_t const_1_10[1] = {0x61};
// b
const buffer_unit_t const_1_11[1] = {0x62};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/23__cat4_0.kex\nSource md5: e946b180723e5ef24b20 174dc2f1119\nSST states: 10\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_7,64);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_5;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_7,64);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_5;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_5,48);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_6;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_3,32);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_7;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_8;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_6,56);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_8,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_11,8);
consume(1);
goto l1_5;
}
goto fail1;
l1_6: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_4,40);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_8,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_11,8);
consume(1);
goto l1_6;
}
goto fail1;
l1_7: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_8,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_11,8);
consume(1);
goto l1_7;
}
goto fail1;
l1_8: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_11,8);
consume(1);
goto l1_8;
}
goto fail1;
l1_9: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_7,64);
consume(1);
goto l1_9;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_10,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_9,16);
consume(1);
goto l1_5;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,951 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// .\xa
const buffer_unit_t const_1_1[2] = {0x2e,0xa};
// ..\xa
const buffer_unit_t const_1_2[3] = {0x2e,0x2e,0xa};
// ...\xa
const buffer_unit_t const_1_3[4] = {0x2e,0x2e,0x2e,0xa};
// ....\xa
const buffer_unit_t const_1_4[5] = {0x2e,0x2e,0x2e,0x2e,0xa};
// .....\xa
const buffer_unit_t const_1_5[6] = {0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ......\xa
const buffer_unit_t const_1_6[7] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// .......\xa
const buffer_unit_t const_1_7[8] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ........\xa
const buffer_unit_t const_1_8[9] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// .........\xa
const buffer_unit_t const_1_9[10] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ..........\xa
const buffer_unit_t const_1_10[11] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ...........\xa
const buffer_unit_t const_1_11[12] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ............\xa
const buffer_unit_t const_1_12[13] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// .............\xa
const buffer_unit_t const_1_13[14] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ..............\xa
const buffer_unit_t const_1_14[15] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// ...............\xa
const buffer_unit_t const_1_15[16] = {0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0xa};
// .a
const buffer_unit_t const_1_16[2] = {0x2e,0x61};
// .b
const buffer_unit_t const_1_17[2] = {0x2e,0x62};
// a
const buffer_unit_t const_1_18[1] = {0x61};
// b
const buffer_unit_t const_1_19[1] = {0x62};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/26__cat8_0.kex\nSource md5: 8123d4d18459f3a150d5eb37785b7283\nSST states: 18\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_15,128);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_9;
}
goto fail1;
l1_1: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_15,128);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_9;
}
goto fail1;
l1_2: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_13,112);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_10;
}
goto fail1;
l1_3: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_11,96);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_11;
}
goto fail1;
l1_4: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_9,80);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_12;
}
goto fail1;
l1_5: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_7,64);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_13;
}
goto fail1;
l1_6: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_5,48);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_14;
}
goto fail1;
l1_7: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_3,32);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_15;
}
goto fail1;
l1_8: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_1,16);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_8;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_16;
}
goto fail1;
l1_9: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_14,120);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_2;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_9;
}
goto fail1;
l1_10: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_12,104);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_3;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_10;
}
goto fail1;
l1_11: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_10,88);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_11;
}
goto fail1;
l1_12: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_8,72);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_5;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_12;
}
goto fail1;
l1_13: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_6,56);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_6;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_13;
}
goto fail1;
l1_14: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_4,40);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_7;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_14;
}
goto fail1;
l1_15: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_2,24);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_16,16);
consume(1);
goto l1_8;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_15;
}
goto fail1;
l1_16: if (!readnext(1, 1))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_19,8);
consume(1);
goto l1_16;
}
goto fail1;
l1_17: if (!readnext(1, 1))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_15,128);
consume(1);
goto l1_17;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
outputarray(const_1_18,8);
consume(1);
goto l1_1;
}
if (((avail >= 1) && ((next[0] == 'b') && 1)))
{
outputarray(const_1_17,16);
consume(1);
goto l1_9;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,584 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// aa;
const buffer_unit_t const_1_1[3] = {0x61,0x61,0x3b};
// aaa.
const buffer_unit_t const_1_2[4] = {0x61,0x61,0x61,0x2e};
// aaaaa.
const buffer_unit_t const_1_3[6] = {0x61,0x61,0x61,0x61,0x61,0x2e};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/30__rep_cat_5_3_2.kex\nSource md5: c0ad3e9c7b246e7c3eb6 1ada8ac90b5\nSST states: 5\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 5))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 5) && (cmp(&next[0],(unsigned char *) "aaaaa",5) && 1)))
{
outputarray(const_1_3,48);
consume(5);
goto l1_1;
}
goto fail1;
l1_1: if (!readnext(3, 3))
{
goto fail1;
}
if (((avail >= 3) && (cmp(&next[0],(unsigned char *) "aaa",3) && 1)))
{
outputarray(const_1_2,32);
consume(3);
goto l1_2;
}
goto fail1;
l1_2: if (!readnext(2, 2))
{
goto fail1;
}
if (((avail >= 2) && (cmp(&next[0],(unsigned char *) "aa",2) && 1)))
{
outputarray(const_1_1,24);
consume(2);
goto l1_3;
}
goto fail1;
l1_3: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 5) && (cmp(&next[0],(unsigned char *) "aaaaa",5) && 1)))
{
outputarray(const_1_3,48);
consume(5);
goto l1_1;
}
goto fail1;
l1_4: if (!readnext(1, 5))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 5) && (cmp(&next[0],(unsigned char *) "aaaaa",5) && 1)))
{
outputarray(const_1_3,48);
consume(5);
goto l1_1;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,584 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// aaaaaaa;
const buffer_unit_t const_1_1[8] = {0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x3b};
// aaaaaaaaaaa.
const buffer_unit_t const_1_2[12] = {0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x2e};
// aaaaaaaaaaaaa.
const buffer_unit_t const_1_3[14] = {0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x2e};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/31__rep_cat_13_11_7.kex\nSource md5: 1ee9134887f0913668fc89b18cc5986e\nSST states: 5\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 13))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 13) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaa",13) && 1)))
{
outputarray(const_1_3,112);
consume(13);
goto l1_1;
}
goto fail1;
l1_1: if (!readnext(11, 11))
{
goto fail1;
}
if (((avail >= 11) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaa",11) && 1)))
{
outputarray(const_1_2,96);
consume(11);
goto l1_2;
}
goto fail1;
l1_2: if (!readnext(7, 7))
{
goto fail1;
}
if (((avail >= 7) && (cmp(&next[0],(unsigned char *) "aaaaaaa",7) && 1)))
{
outputarray(const_1_1,64);
consume(7);
goto l1_3;
}
goto fail1;
l1_3: if (!readnext(1, 13))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 13) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaa",13) && 1)))
{
outputarray(const_1_3,112);
consume(13);
goto l1_1;
}
goto fail1;
l1_4: if (!readnext(1, 13))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 13) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaa",13) && 1)))
{
outputarray(const_1_3,112);
consume(13);
goto l1_1;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,584 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// aaaaaaaaaaaaaaaaa;
const buffer_unit_t const_1_1[18] = {0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x3b};
// aaaaaaaaaaaaaaaaaaa.
const buffer_unit_t const_1_2[20] = {0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x2e};
// aaaaaaaaaaaaaaaaaaaaaaa.
const buffer_unit_t const_1_3[24] = {0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x2e};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/32__rep_cat_23_19_17.kex\nSource md5: e9 2e920 28b746d957a18cefb d9528\nSST states: 5\n");
}
void init()
{
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 23))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 23) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaaaaaaaaaaaa",23) && 1)))
{
outputarray(const_1_3,192);
consume(23);
goto l1_1;
}
goto fail1;
l1_1: if (!readnext(19, 19))
{
goto fail1;
}
if (((avail >= 19) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaaaaaaaa",19) && 1)))
{
outputarray(const_1_2,160);
consume(19);
goto l1_2;
}
goto fail1;
l1_2: if (!readnext(17, 17))
{
goto fail1;
}
if (((avail >= 17) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaaaaaa",17) && 1)))
{
outputarray(const_1_1,144);
consume(17);
goto l1_3;
}
goto fail1;
l1_3: if (!readnext(1, 23))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 23) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaaaaaaaaaaaa",23) && 1)))
{
outputarray(const_1_3,192);
consume(23);
goto l1_1;
}
goto fail1;
l1_4: if (!readnext(1, 23))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 23) && (cmp(&next[0],(unsigned char *) "aaaaaaaaaaaaaaaaaaaaaaa",23) && 1)))
{
outputarray(const_1_3,192);
consume(23);
goto l1_1;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
@@ -0,0 +1,945 @@
#define NUM_PHASES 1
#define BUFFER_UNIT_T uint8_t
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#define RETC_PRINT_USAGE 1
#define RETC_PRINT_INFO 2
#define OUTBUFFER_SIZE (16*1024)
#define INBUFFER_SIZE (16*1024)
#define INITIAL_BUFFER_SIZE (4096*8)
#define OUTBUFFER_STACK_SIZE (1024)
#ifdef FLAG_NOINLINE
#define INLINE static
#endif
#ifndef INLINE
#define INLINE static inline
#endif
#ifndef BUFFER_UNIT_T
#warning "BUFFER_UNIT_T not defined. Falling back to default 'uint8_t'"
#define BUFFER_UNIT_T uint8_t
#endif
#ifndef NUM_PHASES
#error "NUM_PHASES not defined."
#endif
#ifndef OUTSTREAM
#define OUTSTREAM stdout
#endif
// Order of descriptors provided by pipe()
#define READ_FD 0
#define WRITE_FD 1
typedef BUFFER_UNIT_T buffer_unit_t;
typedef struct {
buffer_unit_t *data;
size_t size; /* size in bytes */
size_t bitpos; /* bit offset from data */
} buffer_t;
#define BUFFER_UNIT_SIZE (sizeof(buffer_unit_t))
#define BUFFER_UNIT_BITS (BUFFER_UNIT_SIZE * 8)
unsigned char *next;
buffer_t outbuf;
buffer_t *outbuf_ptr;
size_t count = 0;
unsigned char inbuf[INBUFFER_SIZE*2];
size_t in_size = 0;
int in_cursor = 0;
#define avail (in_size - in_cursor)
// Output buffer stack
typedef struct {
buffer_t **data;
size_t capacity;
size_t size;
} buf_stack;
buf_stack outbuf_stack;
void pushoutbuf(buffer_t *buf) {
if (outbuf_stack.size == outbuf_stack.capacity) {
outbuf_stack.capacity *= 2;
outbuf_stack.data = realloc(outbuf_stack.data, outbuf_stack.capacity*sizeof(buffer_t *));
}
outbuf_stack.data[outbuf_stack.size++] = outbuf_ptr;
outbuf_ptr = buf;
}
void popoutbuf() {
if (outbuf_stack.size <= 0) {
fprintf(stderr, "Error: Tried popping an empty buffer stack");
exit(1);
}
outbuf_ptr = outbuf_stack.data[--outbuf_stack.size];
}
void init_outbuf_stack()
{
outbuf_ptr = &outbuf;
outbuf_stack.size = 0;
outbuf_stack.capacity = OUTBUFFER_STACK_SIZE;
outbuf_stack.data = malloc(OUTBUFFER_STACK_SIZE*sizeof(buffer_t *));
}
// Program interface
void printCompilationInfo();
void init();
void match(int phase);
void buf_flush(buffer_t *buf)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
// If we do not have a single complete word to flush, return.
// Not just an optimization! The zeroing logic below assumes word_index > 0.
if (word_index == 0)
{
return;
}
if (fwrite(buf->data, BUFFER_UNIT_SIZE, word_index, OUTSTREAM) == -1)
{
fprintf(stderr, "Error writing to output stream.\n");
exit(1);
}
// Since partially written words are not flushed, they need to be moved to the
// beginning of the buffer.
if (buf->bitpos % BUFFER_UNIT_BITS != 0)
{
buf->data[0] = buf->data[word_index];
}
else
{
// If we flushed everything, re-establish the invariant that the word at the
// cursor is garbage-free by simply zeroing it.
buf->data[0] = 0;
}
// Rewind cursor
buf->bitpos = buf->bitpos - word_index * BUFFER_UNIT_BITS;
}
// Write first 'bits' of 'w' to 'buf', starting from the MOST significant bit.
// Precondition: Remaining bits of 'w' must be zero.
INLINE
bool buf_writeconst(buffer_t *buf, buffer_unit_t w, size_t bits)
{
size_t word_index = buf->bitpos / BUFFER_UNIT_BITS;
size_t offset = buf->bitpos % BUFFER_UNIT_BITS;
size_t bits_available = BUFFER_UNIT_BITS - offset;
#ifdef FLAG_WORDALIGNED
buf->data[word_index] = w;
#else
buf->data[word_index] |= w >> offset;
// test for offset > 0 important; shifting by the word size is undefined behaviour.
buf->data[word_index+1] = (offset == 0) ? 0 : (w << bits_available);
#endif
buf->bitpos += bits;
// Is cursor in last word?
return (buf->bitpos >= buf->size * 8 - BUFFER_UNIT_BITS);
}
void buf_resize(buffer_t *buf, size_t shift)
{
size_t new_size = buf->size << shift;
buffer_unit_t *data2 = calloc(new_size, 1);
memcpy(data2, buf->data, buf->size);
free(buf->data);
buf->data = data2;
buf->size = new_size;
}
INLINE
void buf_writearray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
if (dst->bitpos % BUFFER_UNIT_BITS == 0)
{
int count = (bits / BUFFER_UNIT_BITS) + (bits % BUFFER_UNIT_BITS ? 1 : 0);
memcpy(&dst->data[dst->bitpos / BUFFER_UNIT_BITS], arr, count * BUFFER_UNIT_SIZE);
dst->bitpos += bits;
dst->data[dst->bitpos / BUFFER_UNIT_BITS] = 0;
} else
{
int word_index = 0;
for (word_index = 0; word_index < bits / BUFFER_UNIT_BITS; word_index++)
{
buf_writeconst(dst, arr[word_index], BUFFER_UNIT_BITS);
}
if (bits % BUFFER_UNIT_BITS != 0)
{
buf_writeconst(dst, arr[word_index], bits % BUFFER_UNIT_BITS);
}
}
}
INLINE
void reset(buffer_t *buf)
{
buf->data[0] = 0;
buf->bitpos = 0;
}
void init_buffer(buffer_t *buf)
{
buf->data = malloc(INITIAL_BUFFER_SIZE);
buf->size = INITIAL_BUFFER_SIZE;
buf->bitpos = 0;
buf->data[0] = 0;
}
void destroy_buffer(buffer_t *buf)
{
if (buf->data != NULL)
free(buf->data);
buf->data = NULL;
}
INLINE
void outputconst(buffer_unit_t w, size_t bits)
{
if (buf_writeconst(outbuf_ptr, w, bits))
{
if (outbuf_stack.size == 0)
{
buf_flush(outbuf_ptr);
}
}
}
INLINE
void appendarray(buffer_t *dst, const buffer_unit_t *arr, size_t bits)
{
size_t total_bits = dst->bitpos + bits;
if (total_bits >= (dst->size - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
size_t shift = 1;
while (total_bits >= ((dst->size << shift) - 1) * BUFFER_UNIT_BITS * BUFFER_UNIT_SIZE)
{
shift++;
}
buf_resize(dst, shift);
}
buf_writearray(dst, arr, bits);
}
INLINE
void append(buffer_t *buf, buffer_unit_t w, size_t bits)
{
if (buf_writeconst(buf, w, bits))
{
buf_resize(buf, 1);
}
}
INLINE
void concat(buffer_t *dst, buffer_t *src)
{
appendarray(dst, src->data, src->bitpos);
}
INLINE
void outputarray(const buffer_unit_t *arr, size_t bits)
{
int word_count = bits / BUFFER_UNIT_BITS;
// Write completed words
size_t word_index = 0;
for (word_index = 0; word_index < word_count; word_index++)
{
outputconst(arr[word_index], BUFFER_UNIT_BITS);
}
int remaining = bits % BUFFER_UNIT_BITS;
if (remaining != 0)
{
outputconst(arr[bits / BUFFER_UNIT_BITS], remaining);
}
}
INLINE
void output(buffer_t *buf)
{
outputarray(buf->data, buf->bitpos);
}
INLINE
void consume(int c)
{
count += c;
in_cursor += c;
next += c;
}
INLINE
int readnext(int minCount, int maxCount)
{
// We can always take epsilon transitions
if (minCount == 0) return 1;
if (avail < maxCount)
{
int remaining = avail;
memmove(&inbuf[INBUFFER_SIZE - remaining], &inbuf[INBUFFER_SIZE+in_cursor], remaining);
in_cursor = -remaining;
in_size = fread(&inbuf[INBUFFER_SIZE], 1, INBUFFER_SIZE, stdin);
}
if (avail < minCount)
{
return 0;
}
next = &inbuf[INBUFFER_SIZE+in_cursor];
return 1;
}
INLINE
int cmp(unsigned char *str1, unsigned char *str2, int l)
{
int i = 0;
for (i = 0; i < l; i++)
{
if (str1[i] != str2[i])
return 0;
}
return 1;
}
void printUsage(char *name)
{
fprintf(stdout, "Normal usage: %s < infile > outfile\n", name);
fprintf(stdout, "- \"%s\": reads from stdin and writes to stdout.\n", name);
fprintf(stdout, "- \"%s -i\": prints compilation info.\n", name);
fprintf(stdout, "- \"%s -t\": runs normally, but prints timing to stderr.\n", name);
}
void flush_outbuf()
{
if (outbuf.bitpos % BUFFER_UNIT_BITS != 0)
{
outputconst(0, BUFFER_UNIT_BITS);
}
if (outbuf_stack.size > 0)
{
fprintf(stderr, "Error: buffer stack ended non-empty\n");
exit(1);
}
buf_flush(&outbuf);
}
void init_outbuf()
{
outbuf.size = OUTBUFFER_SIZE + BUFFER_UNIT_SIZE;
outbuf.data = malloc(outbuf.size);
reset(&outbuf);
init_outbuf_stack();
}
void run(int phase)
{
init_outbuf();
init();
match(phase);
flush_outbuf();
}
#ifndef FLAG_NOMAIN
static struct option long_options[] = {
{ "phase", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
bool do_timing = false;
int c;
int option_index = 0;
int phase;
bool do_phase = false;
while ((c = getopt_long (argc, argv, "ihtp:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'i':
printCompilationInfo();
return RETC_PRINT_INFO;
case 't':
do_timing = true;
break;
case 'p':
phase = atoi(optarg);
do_phase = true;
break;
case 'h':
default:
printUsage(argv[0]);
return RETC_PRINT_USAGE;
}
}
struct timeval time_before, time_after, time_result;
long int millis;
if(do_timing)
{
gettimeofday(&time_before, NULL);
}
if (do_phase)
{
run(phase);
}
else
{
// set up a pipeline
// stdin -> prog --phase 1 -> prog --phase 2 -> ... -> prog --phase n -> stdout
int orig_stdout = dup(STDOUT_FILENO);
int pipes[NUM_PHASES-1][2];
int i;
for (i = 1; i < NUM_PHASES; i++)
{
if (i != 1) close(pipes[i-2][WRITE_FD]);
if (pipe(pipes[i-1]) != 0)
{
fprintf(stderr, "Error creating pipe %d.", i);
return 1;
}
dup2(pipes[i-1][WRITE_FD], STDOUT_FILENO);
if (! fork())
{
close(orig_stdout);
close(pipes[i-1][READ_FD]);
// Should use snprintf, but I assume something else will break before we hit 10^19 phases.
char phase[20] = {0};
sprintf(phase, "%d", i);
char *args[] = { argv[0], "--phase", phase, 0 };
return main(3, args);
}
close(STDIN_FILENO);
dup2(pipes[i-1][READ_FD], STDIN_FILENO);
}
#if NUM_PHASES>1
close(pipes[NUM_PHASES-2][WRITE_FD]);
dup2(orig_stdout, STDOUT_FILENO);
#endif
// Run last phase in-process
run(NUM_PHASES);
}
if (do_timing)
{
gettimeofday(&time_after, NULL);
timersub(&time_after, &time_before, &time_result);
// A timeval contains seconds and microseconds.
millis = time_result.tv_sec * 1000 + time_result.tv_usec / 1000;
fprintf(stderr, "time (ms): %ld\n", millis);
}
return 0;
}
#endif
/* no tables */
buffer_t buf_0;
buffer_t buf_1;
buffer_t buf_2;
buffer_t buf_3;
buffer_t buf_4;
// \xa
const buffer_unit_t const_1_0[1] = {0xa};
// .
const buffer_unit_t const_1_1[1] = {0x2e};
// a
const buffer_unit_t const_1_2[1] = {0x61};
// a.
const buffer_unit_t const_1_3[2] = {0x61,0x2e};
// aa
const buffer_unit_t const_1_4[2] = {0x61,0x61};
// aa.
const buffer_unit_t const_1_5[3] = {0x61,0x61,0x2e};
// aa.\xa
const buffer_unit_t const_1_6[4] = {0x61,0x61,0x2e,0xa};
// aa.aa
const buffer_unit_t const_1_7[5] = {0x61,0x61,0x2e,0x61,0x61};
// aa.aa.
const buffer_unit_t const_1_8[6] = {0x61,0x61,0x2e,0x61,0x61,0x2e};
// aa.aa.aa
const buffer_unit_t const_1_9[8] = {0x61,0x61,0x2e,0x61,0x61,0x2e,0x61,0x61};
// aaa.
const buffer_unit_t const_1_10[4] = {0x61,0x61,0x61,0x2e};
// aaa.\xa
const buffer_unit_t const_1_11[5] = {0x61,0x61,0x61,0x2e,0xa};
// aaa.aa
const buffer_unit_t const_1_12[6] = {0x61,0x61,0x61,0x2e,0x61,0x61};
// aaa.aa.
const buffer_unit_t const_1_13[7] = {0x61,0x61,0x61,0x2e,0x61,0x61,0x2e};
// aaa.aaa.\xa
const buffer_unit_t const_1_14[9] = {0x61,0x61,0x61,0x2e,0x61,0x61,0x61,0x2e,0xa};
// aaaaa.
const buffer_unit_t const_1_15[6] = {0x61,0x61,0x61,0x61,0x61,0x2e};
// aaaaa.\xa
const buffer_unit_t const_1_16[7] = {0x61,0x61,0x61,0x61,0x61,0x2e,0xa};
// aaaaa.a
const buffer_unit_t const_1_17[7] = {0x61,0x61,0x61,0x61,0x61,0x2e,0x61};
// aaaaa.aa.
const buffer_unit_t const_1_18[9] = {0x61,0x61,0x61,0x61,0x61,0x2e,0x61,0x61,0x2e};
void printCompilationInfo()
{
fprintf(stdout, "No object file generated!\nOptions:\nSST optimization level: 3\nWord size: UInt8T\nIdentity tables removed: False\n\nSource file: ../../../benchmarks/submatch_dfa_aot/src/kleenex/33__rep_alt_5_3_2.kex\nSource md5: f832418543 bcca51b128bc3 b7e1826\nSST states: 8\n");
}
void init()
{
init_buffer(&buf_1);
init_buffer(&buf_2);
init_buffer(&buf_3);
init_buffer(&buf_4);
}
void match1()
{
int i = 0;
goto l1_0;
l1_0: if (!readnext(1, 5))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 2) && (cmp(&next[0],(unsigned char *) "aa",2) && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 5) && (cmp(&next[3],(unsigned char *) "aa",2) && 1)))
{
reset(&buf_4);
appendarray(&buf_4,const_1_1,8);
reset(&buf_3);
appendarray(&buf_3,const_1_4,16);
reset(&buf_2);
appendarray(&buf_2,const_1_3,16);
consume(5);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_1,8);
reset(&buf_1);
appendarray(&buf_1,const_1_3,16);
outputarray(const_1_4,16);
consume(3);
goto l1_5;
}
outputarray(const_1_5,24);
consume(2);
goto l1_1;
}
goto fail1;
l1_1: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 2) && (cmp(&next[0],(unsigned char *) "aa",2) && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 5) && (cmp(&next[3],(unsigned char *) "aa",2) && 1)))
{
reset(&buf_4);
appendarray(&buf_4,const_1_5,24);
reset(&buf_3);
reset(&buf_2);
appendarray(&buf_2,const_1_10,32);
consume(5);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
reset(&buf_1);
appendarray(&buf_1,const_1_10,32);
consume(3);
goto l1_5;
}
outputarray(const_1_5,24);
consume(2);
goto l1_1;
}
goto fail1;
l1_2: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_3);
outputarray(const_1_6,32);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
if (((avail >= 2) && ((next[1] == 'a') && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 4) && ((next[3] == 'a') && 1)))
{
if (((avail >= 5) && ((next[4] == 'a') && 1)))
{
output(&buf_1);
consume(5);
goto l1_3;
}
reset(&buf_4);
appendarray(&buf_4,const_1_3,16);
reset(&buf_3);
appendarray(&buf_3,const_1_2,8);
reset(&buf_2);
appendarray(&buf_2,const_1_5,24);
output(&buf_1);
consume(4);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_3,16);
output(&buf_1);
outputarray(const_1_2,8);
reset(&buf_1);
appendarray(&buf_1,const_1_5,24);
consume(3);
goto l1_2;
}
reset(&buf_3);
appendarray(&buf_3,const_1_3,16);
output(&buf_1);
outputarray(const_1_2,8);
reset(&buf_1);
appendarray(&buf_1,const_1_5,24);
consume(2);
goto l1_5;
}
output(&buf_1);
outputarray(const_1_5,24);
consume(1);
goto l1_1;
}
goto fail1;
l1_3: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_14,72);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
if (((avail >= 2) && ((next[1] == 'a') && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 4) && ((next[3] == 'a') && 1)))
{
if (((avail >= 5) && ((next[4] == 'a') && 1)))
{
outputarray(const_1_15,48);
consume(5);
goto l1_3;
}
reset(&buf_4);
appendarray(&buf_4,const_1_3,16);
reset(&buf_3);
appendarray(&buf_3,const_1_2,8);
reset(&buf_2);
appendarray(&buf_2,const_1_5,24);
outputarray(const_1_15,48);
consume(4);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_3,16);
reset(&buf_1);
appendarray(&buf_1,const_1_5,24);
outputarray(const_1_17,56);
consume(3);
goto l1_2;
}
reset(&buf_3);
appendarray(&buf_3,const_1_3,16);
reset(&buf_1);
appendarray(&buf_1,const_1_5,24);
outputarray(const_1_17,56);
consume(2);
goto l1_5;
}
outputarray(const_1_18,72);
consume(1);
goto l1_1;
}
goto fail1;
l1_4: if (!readnext(1, 5))
{
goto accept1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 2) && (cmp(&next[0],(unsigned char *) "aa",2) && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 5) && (cmp(&next[3],(unsigned char *) "aa",2) && 1)))
{
reset(&buf_4);
appendarray(&buf_4,const_1_5,24);
reset(&buf_3);
reset(&buf_2);
appendarray(&buf_2,const_1_10,32);
consume(5);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
reset(&buf_1);
appendarray(&buf_1,const_1_10,32);
consume(3);
goto l1_5;
}
outputarray(const_1_5,24);
consume(2);
goto l1_1;
}
goto fail1;
l1_5: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_0,8);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
if (((avail >= 2) && ((next[1] == 'a') && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 4) && ((next[3] == 'a') && 1)))
{
if (((avail >= 5) && ((next[4] == 'a') && 1)))
{
reset(&buf_4);
appendarray(&buf_4,const_1_5,24);
reset(&buf_3);
reset(&buf_2);
appendarray(&buf_2,const_1_10,32);
output(&buf_1);
consume(5);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
output(&buf_1);
reset(&buf_1);
appendarray(&buf_1,const_1_10,32);
consume(4);
goto l1_2;
}
appendarray(&buf_3,const_1_7,40);
consume(3);
goto l1_7;
}
appendarray(&buf_3,const_1_5,24);
appendarray(&buf_1,const_1_5,24);
consume(2);
goto l1_5;
}
output(&buf_3);
outputarray(const_1_5,24);
consume(1);
goto l1_1;
}
goto fail1;
l1_6: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
outputarray(const_1_16,56);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
if (((avail >= 2) && ((next[1] == 'a') && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 4) && ((next[3] == 'a') && 1)))
{
if (((avail >= 5) && ((next[4] == 'a') && 1)))
{
reset(&buf_4);
appendarray(&buf_4,const_1_5,24);
reset(&buf_3);
reset(&buf_2);
appendarray(&buf_2,const_1_10,32);
outputarray(const_1_15,48);
consume(5);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
reset(&buf_1);
appendarray(&buf_1,const_1_10,32);
outputarray(const_1_15,48);
consume(4);
goto l1_2;
}
concat(&buf_3,&buf_2);
appendarray(&buf_3,const_1_12,48);
reset(&buf_1);
appendarray(&buf_1,const_1_15,48);
consume(3);
goto l1_7;
}
concat(&buf_3,&buf_2);
appendarray(&buf_3,const_1_10,32);
reset(&buf_1);
appendarray(&buf_1,const_1_18,72);
consume(2);
goto l1_5;
}
output(&buf_3);
output(&buf_2);
outputarray(const_1_10,32);
consume(1);
goto l1_1;
}
goto fail1;
l1_7: if (!readnext(1, 5))
{
goto fail1;
}
if (((avail >= 1) && ((next[0] == 10) && 1)))
{
output(&buf_1);
outputarray(const_1_11,40);
consume(1);
goto l1_4;
}
if (((avail >= 1) && ((next[0] == 'a') && 1)))
{
if (((avail >= 2) && ((next[1] == 'a') && 1)))
{
if (((avail >= 3) && ((next[2] == 'a') && 1)))
{
if (((avail >= 4) && ((next[3] == 'a') && 1)))
{
if (((avail >= 5) && ((next[4] == 'a') && 1)))
{
reset(&buf_4);
appendarray(&buf_4,const_1_5,24);
reset(&buf_3);
reset(&buf_2);
appendarray(&buf_2,const_1_10,32);
output(&buf_1);
outputarray(const_1_10,32);
consume(5);
goto l1_6;
}
reset(&buf_3);
appendarray(&buf_3,const_1_5,24);
output(&buf_1);
outputarray(const_1_10,32);
reset(&buf_1);
appendarray(&buf_1,const_1_10,32);
consume(4);
goto l1_2;
}
reset(&buf_3);
appendarray(&buf_3,const_1_9,64);
output(&buf_1);
reset(&buf_1);
appendarray(&buf_1,const_1_10,32);
consume(3);
goto l1_7;
}
reset(&buf_3);
appendarray(&buf_3,const_1_8,48);
output(&buf_1);
reset(&buf_1);
appendarray(&buf_1,const_1_13,56);
consume(2);
goto l1_5;
}
output(&buf_1);
outputarray(const_1_8,48);
consume(1);
goto l1_1;
}
goto fail1;
accept1:
return;
fail1:
fprintf(stderr, "Match error at input symbol %zu!\n", count);
exit(1);
}
void match(int phase)
{
switch(phase) {
case 1: match1(); break;
default:
fprintf(stderr, "Invalid phase: %d given\n", phase);
exit(1);
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,684 @@
#line 1 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
#include "ragel/common.c"
const char *delim = "\n";
#line 42 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
#line 12 "gen/ragel/04__apache_log.c"
static const int apache_log_start = 25;
static const int apache_log_first_final = 25;
static const int apache_log_error = 0;
static const int apache_log_en_main = 25;
#line 44 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
static void lex(Input *in, Output *out)
{
char *p = in->p;
char *pe = in->pe;
const char
*h1, *i1, *a1, *d1, *r1, *s1, *z1, *u1, *g1,
*h2, *i2, *a2, *d2, *r2, *s2, *z2, *u2, *g2;
int cs;
#line 33 "gen/ragel/04__apache_log.c"
{
cs = (int)apache_log_start;
}
#line 55 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
#line 41 "gen/ragel/04__apache_log.c"
{
switch ( cs ) {
case 25:
goto st_case_25;
case 0:
goto st_case_0;
case 1:
goto st_case_1;
case 2:
goto st_case_2;
case 3:
goto st_case_3;
case 4:
goto st_case_4;
case 5:
goto st_case_5;
case 6:
goto st_case_6;
case 7:
goto st_case_7;
case 8:
goto st_case_8;
case 9:
goto st_case_9;
case 10:
goto st_case_10;
case 11:
goto st_case_11;
case 12:
goto st_case_12;
case 13:
goto st_case_13;
case 14:
goto st_case_14;
case 15:
goto st_case_15;
case 16:
goto st_case_16;
case 17:
goto st_case_17;
case 18:
goto st_case_18;
case 19:
goto st_case_19;
case 20:
goto st_case_20;
case 21:
goto st_case_21;
case 22:
goto st_case_22;
case 23:
goto st_case_23;
case 24:
goto st_case_24;
}
_ctr41:
{
#line 27 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
g2 = p; }
#line 102 "gen/ragel/04__apache_log.c"
{
#line 28 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
OUT("host: ", h1, h2);
OUT("userid: ", i1, i2);
OUT("authuser: ", a1, a2);
OUT("date: ", d1, d2);
OUT("request: ", r1, r2);
OUT("status: ", s1, s2);
OUT("size: ", z1, z2);
OUT("url: ", u1, u2);
OUT("agent: ", g1, g2);
outc(out, '\n');
}
#line 119 "gen/ragel/04__apache_log.c"
goto _st25;
_st25:
p+= 1;
st_case_25:
if ( p == pe )
goto _out25;
if ( ( (*( p))) == 46 ) {
goto _ctr44;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr44;
}
goto _st0;
_st0:
st_case_0:
goto _out0;
_ctr44:
{
#line 19 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
h1 = p; }
#line 142 "gen/ragel/04__apache_log.c"
goto _st1;
_st1:
p+= 1;
st_case_1:
if ( p == pe )
goto _out1;
switch( ( (*( p))) ) {
case 9: {
goto _ctr2;
}
case 32: {
goto _ctr2;
}
case 46: {
goto _st1;
}
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st1;
}
goto _st0;
_ctr2:
{
#line 19 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
h2 = p; }
#line 170 "gen/ragel/04__apache_log.c"
goto _st2;
_st2:
p+= 1;
st_case_2:
if ( p == pe )
goto _out2;
switch( ( (*( p))) ) {
case 9: {
goto _st2;
}
case 32: {
goto _st2;
}
case 45: {
goto _ctr4;
}
}
goto _st0;
_ctr4:
{
#line 20 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
i1 = p; }
#line 195 "gen/ragel/04__apache_log.c"
goto _st3;
_st3:
p+= 1;
st_case_3:
if ( p == pe )
goto _out3;
switch( ( (*( p))) ) {
case 9: {
goto _ctr6;
}
case 32: {
goto _ctr6;
}
}
goto _st0;
_ctr6:
{
#line 20 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
i2 = p; }
#line 217 "gen/ragel/04__apache_log.c"
goto _st4;
_st4:
p+= 1;
st_case_4:
if ( p == pe )
goto _out4;
switch( ( (*( p))) ) {
case 9: {
goto _st4;
}
case 32: {
goto _st4;
}
case 45: {
goto _ctr8;
}
}
goto _st0;
_ctr8:
{
#line 21 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
a1 = p; }
#line 242 "gen/ragel/04__apache_log.c"
goto _st5;
_st5:
p+= 1;
st_case_5:
if ( p == pe )
goto _out5;
switch( ( (*( p))) ) {
case 9: {
goto _ctr10;
}
case 32: {
goto _ctr10;
}
}
goto _st0;
_ctr10:
{
#line 21 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
a2 = p; }
#line 264 "gen/ragel/04__apache_log.c"
goto _st6;
_st6:
p+= 1;
st_case_6:
if ( p == pe )
goto _out6;
switch( ( (*( p))) ) {
case 9: {
goto _st6;
}
case 32: {
goto _st6;
}
case 91: {
goto _ctr12;
}
}
goto _st0;
_ctr12:
{
#line 22 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
d1 = p; }
#line 289 "gen/ragel/04__apache_log.c"
goto _st7;
_st7:
p+= 1;
st_case_7:
if ( p == pe )
goto _out7;
switch( ( (*( p))) ) {
case 10: {
goto _st0;
}
case 93: {
goto _st0;
}
}
goto _st8;
_st8:
p+= 1;
st_case_8:
if ( p == pe )
goto _out8;
switch( ( (*( p))) ) {
case 10: {
goto _st0;
}
case 93: {
goto _st9;
}
}
goto _st8;
_st9:
p+= 1;
st_case_9:
if ( p == pe )
goto _out9;
switch( ( (*( p))) ) {
case 9: {
goto _ctr16;
}
case 32: {
goto _ctr16;
}
}
goto _st0;
_ctr16:
{
#line 22 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
d2 = p; }
#line 339 "gen/ragel/04__apache_log.c"
goto _st10;
_st10:
p+= 1;
st_case_10:
if ( p == pe )
goto _out10;
switch( ( (*( p))) ) {
case 9: {
goto _st10;
}
case 32: {
goto _st10;
}
case 34: {
goto _ctr18;
}
}
goto _st0;
_ctr18:
{
#line 23 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
r1 = p; }
#line 364 "gen/ragel/04__apache_log.c"
goto _st11;
_st11:
p+= 1;
st_case_11:
if ( p == pe )
goto _out11;
switch( ( (*( p))) ) {
case 10: {
goto _st0;
}
case 34: {
goto _st0;
}
}
goto _st12;
_st12:
p+= 1;
st_case_12:
if ( p == pe )
goto _out12;
switch( ( (*( p))) ) {
case 10: {
goto _st0;
}
case 34: {
goto _st13;
}
}
goto _st12;
_st13:
p+= 1;
st_case_13:
if ( p == pe )
goto _out13;
switch( ( (*( p))) ) {
case 9: {
goto _ctr22;
}
case 32: {
goto _ctr22;
}
}
goto _st0;
_ctr22:
{
#line 23 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
r2 = p; }
#line 414 "gen/ragel/04__apache_log.c"
goto _st14;
_st14:
p+= 1;
st_case_14:
if ( p == pe )
goto _out14;
switch( ( (*( p))) ) {
case 9: {
goto _st14;
}
case 32: {
goto _st14;
}
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr24;
}
goto _st0;
_ctr24:
{
#line 24 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
s1 = p; }
#line 439 "gen/ragel/04__apache_log.c"
goto _st15;
_st15:
p+= 1;
st_case_15:
if ( p == pe )
goto _out15;
switch( ( (*( p))) ) {
case 9: {
goto _ctr26;
}
case 32: {
goto _ctr26;
}
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st15;
}
goto _st0;
_ctr26:
{
#line 24 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
s2 = p; }
#line 464 "gen/ragel/04__apache_log.c"
goto _st16;
_st16:
p+= 1;
st_case_16:
if ( p == pe )
goto _out16;
switch( ( (*( p))) ) {
case 9: {
goto _st16;
}
case 32: {
goto _st16;
}
case 45: {
goto _ctr28;
}
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr29;
}
goto _st0;
_ctr28:
{
#line 25 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
z1 = p; }
#line 492 "gen/ragel/04__apache_log.c"
goto _st17;
_st17:
p+= 1;
st_case_17:
if ( p == pe )
goto _out17;
switch( ( (*( p))) ) {
case 9: {
goto _ctr31;
}
case 32: {
goto _ctr31;
}
}
goto _st0;
_ctr31:
{
#line 25 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
z2 = p; }
#line 514 "gen/ragel/04__apache_log.c"
goto _st18;
_st18:
p+= 1;
st_case_18:
if ( p == pe )
goto _out18;
switch( ( (*( p))) ) {
case 9: {
goto _st18;
}
case 32: {
goto _st18;
}
case 34: {
goto _ctr33;
}
}
goto _st0;
_ctr33:
{
#line 26 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
u1 = p; }
#line 539 "gen/ragel/04__apache_log.c"
goto _st19;
_st19:
p+= 1;
st_case_19:
if ( p == pe )
goto _out19;
switch( ( (*( p))) ) {
case 10: {
goto _st0;
}
case 34: {
goto _st20;
}
}
goto _st19;
_st20:
p+= 1;
st_case_20:
if ( p == pe )
goto _out20;
switch( ( (*( p))) ) {
case 9: {
goto _ctr36;
}
case 32: {
goto _ctr36;
}
}
goto _st0;
_ctr36:
{
#line 26 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
u2 = p; }
#line 575 "gen/ragel/04__apache_log.c"
goto _st21;
_st21:
p+= 1;
st_case_21:
if ( p == pe )
goto _out21;
switch( ( (*( p))) ) {
case 9: {
goto _st21;
}
case 32: {
goto _st21;
}
case 34: {
goto _ctr38;
}
}
goto _st0;
_ctr38:
{
#line 27 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
g1 = p; }
#line 600 "gen/ragel/04__apache_log.c"
goto _st22;
_st22:
p+= 1;
st_case_22:
if ( p == pe )
goto _out22;
switch( ( (*( p))) ) {
case 10: {
goto _st0;
}
case 34: {
goto _st23;
}
}
goto _st22;
_st23:
p+= 1;
st_case_23:
if ( p == pe )
goto _out23;
if ( ( (*( p))) == 10 ) {
goto _ctr41;
}
goto _st0;
_ctr29:
{
#line 25 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
z1 = p; }
#line 631 "gen/ragel/04__apache_log.c"
goto _st24;
_st24:
p+= 1;
st_case_24:
if ( p == pe )
goto _out24;
switch( ( (*( p))) ) {
case 9: {
goto _ctr31;
}
case 32: {
goto _ctr31;
}
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st24;
}
goto _st0;
_out25: cs = 25; goto _out;
_out0: cs = 0; goto _out;
_out1: cs = 1; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
_out5: cs = 5; goto _out;
_out6: cs = 6; goto _out;
_out7: cs = 7; goto _out;
_out8: cs = 8; goto _out;
_out9: cs = 9; goto _out;
_out10: cs = 10; goto _out;
_out11: cs = 11; goto _out;
_out12: cs = 12; goto _out;
_out13: cs = 13; goto _out;
_out14: cs = 14; goto _out;
_out15: cs = 15; goto _out;
_out16: cs = 16; goto _out;
_out17: cs = 17; goto _out;
_out18: cs = 18; goto _out;
_out19: cs = 19; goto _out;
_out20: cs = 20; goto _out;
_out21: cs = 21; goto _out;
_out22: cs = 22; goto _out;
_out23: cs = 23; goto _out;
_out24: cs = 24; goto _out;
_out: {}
}
#line 56 "../../../benchmarks/submatch_dfa_aot/src/ragel/04__apache_log.rl"
in->p = p;
in->pe = pe;
}
@@ -0,0 +1,690 @@
#line 1 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
#include "ragel/common.c"
const char *delim = "\n";
#line 35 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
#line 12 "gen/ragel/05__datetime.c"
static const int datetime_start = 35;
static const int datetime_first_final = 35;
static const int datetime_error = 0;
static const int datetime_en_main = 35;
#line 37 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
static void lex(Input *in, Output *out)
{
char *p = in->p;
char *pe = in->pe;
const char
*s1, *y1, *h1, *m1, *d1, *M1, *z1,
*s2, *y2, *h2, *m2, *d2, *M2, *z2;
int cs;
#line 33 "gen/ragel/05__datetime.c"
{
cs = (int)datetime_start;
}
#line 48 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
#line 41 "gen/ragel/05__datetime.c"
{
switch ( cs ) {
case 35:
goto st_case_35;
case 0:
goto st_case_0;
case 1:
goto st_case_1;
case 2:
goto st_case_2;
case 3:
goto st_case_3;
case 4:
goto st_case_4;
case 5:
goto st_case_5;
case 6:
goto st_case_6;
case 7:
goto st_case_7;
case 8:
goto st_case_8;
case 9:
goto st_case_9;
case 10:
goto st_case_10;
case 11:
goto st_case_11;
case 12:
goto st_case_12;
case 13:
goto st_case_13;
case 14:
goto st_case_14;
case 15:
goto st_case_15;
case 16:
goto st_case_16;
case 17:
goto st_case_17;
case 18:
goto st_case_18;
case 19:
goto st_case_19;
case 20:
goto st_case_20;
case 21:
goto st_case_21;
case 22:
goto st_case_22;
case 23:
goto st_case_23;
case 24:
goto st_case_24;
case 25:
goto st_case_25;
case 26:
goto st_case_26;
case 27:
goto st_case_27;
case 28:
goto st_case_28;
case 29:
goto st_case_29;
case 30:
goto st_case_30;
case 31:
goto st_case_31;
case 32:
goto st_case_32;
case 33:
goto st_case_33;
case 34:
goto st_case_34;
}
_ctr43:
{
#line 22 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
z2 = p; }
#line 122 "gen/ragel/05__datetime.c"
{
#line 23 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
OUT("year: ", y1, y2);
OUT("month: ", m1, m2);
OUT("day: ", d1, d2);
OUT("hours: ", h1, h2);
OUT("minutes: ", M1, M2);
OUT("seconds: ", s1, s2);
OUT("tz: ", z1, z2);
outc(out, '\n');
}
#line 137 "gen/ragel/05__datetime.c"
goto _st35;
_st35:
p+= 1;
st_case_35:
if ( p == pe )
goto _out35;
if ( ( (*( p))) == 48 ) {
goto _ctr53;
}
if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr54;
}
goto _st0;
_st0:
st_case_0:
goto _out0;
_ctr53:
{
#line 16 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
y1 = p; }
#line 160 "gen/ragel/05__datetime.c"
goto _st1;
_st1:
p+= 1;
st_case_1:
if ( p == pe )
goto _out1;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st2;
}
goto _st0;
_st2:
p+= 1;
st_case_2:
if ( p == pe )
goto _out2;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st3;
}
goto _st0;
_st3:
p+= 1;
st_case_3:
if ( p == pe )
goto _out3;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st4;
}
goto _st0;
_st4:
p+= 1;
st_case_4:
if ( p == pe )
goto _out4;
if ( ( (*( p))) == 45 ) {
goto _ctr5;
}
goto _st0;
_ctr5:
{
#line 16 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
y2 = p; }
#line 204 "gen/ragel/05__datetime.c"
goto _st5;
_st5:
p+= 1;
st_case_5:
if ( p == pe )
goto _out5;
switch( ( (*( p))) ) {
case 48: {
goto _ctr7;
}
case 49: {
goto _ctr8;
}
}
goto _st0;
_ctr7:
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
m1 = p; }
#line 226 "gen/ragel/05__datetime.c"
goto _st6;
_st6:
p+= 1;
st_case_6:
if ( p == pe )
goto _out6;
if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st7;
}
goto _st0;
_st7:
p+= 1;
st_case_7:
if ( p == pe )
goto _out7;
if ( ( (*( p))) == 45 ) {
goto _ctr11;
}
goto _st0;
_ctr11:
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
m2 = p; }
#line 252 "gen/ragel/05__datetime.c"
goto _st8;
_st8:
p+= 1;
st_case_8:
if ( p == pe )
goto _out8;
switch( ( (*( p))) ) {
case 48: {
goto _ctr13;
}
case 51: {
goto _ctr15;
}
}
if ( 49 <= ( (*( p))) && ( (*( p))) <= 50 ) {
goto _ctr14;
}
goto _st0;
_ctr13:
{
#line 18 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
d1 = p; }
#line 277 "gen/ragel/05__datetime.c"
goto _st9;
_st9:
p+= 1;
st_case_9:
if ( p == pe )
goto _out9;
if ( 49 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st10;
}
goto _st0;
_st10:
p+= 1;
st_case_10:
if ( p == pe )
goto _out10;
if ( ( (*( p))) == 84 ) {
goto _ctr18;
}
goto _st0;
_ctr18:
{
#line 18 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
d2 = p; }
#line 303 "gen/ragel/05__datetime.c"
goto _st11;
_st11:
p+= 1;
st_case_11:
if ( p == pe )
goto _out11;
if ( ( (*( p))) == 50 ) {
goto _ctr21;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 49 ) {
goto _ctr20;
}
goto _st0;
_ctr20:
{
#line 19 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
h1 = p; }
#line 323 "gen/ragel/05__datetime.c"
goto _st12;
_st12:
p+= 1;
st_case_12:
if ( p == pe )
goto _out12;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st13;
}
goto _st0;
_st13:
p+= 1;
st_case_13:
if ( p == pe )
goto _out13;
if ( ( (*( p))) == 58 ) {
goto _ctr24;
}
goto _st0;
_ctr24:
{
#line 19 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
h2 = p; }
#line 349 "gen/ragel/05__datetime.c"
goto _st14;
_st14:
p+= 1;
st_case_14:
if ( p == pe )
goto _out14;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 53 ) {
goto _ctr26;
}
goto _st0;
_ctr26:
{
#line 20 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
M1 = p; }
#line 366 "gen/ragel/05__datetime.c"
goto _st15;
_st15:
p+= 1;
st_case_15:
if ( p == pe )
goto _out15;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st16;
}
goto _st0;
_st16:
p+= 1;
st_case_16:
if ( p == pe )
goto _out16;
if ( ( (*( p))) == 58 ) {
goto _ctr29;
}
goto _st0;
_ctr29:
{
#line 20 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
M2 = p; }
#line 392 "gen/ragel/05__datetime.c"
goto _st17;
_st17:
p+= 1;
st_case_17:
if ( p == pe )
goto _out17;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 53 ) {
goto _ctr31;
}
goto _st0;
_ctr31:
{
#line 21 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
s1 = p; }
#line 409 "gen/ragel/05__datetime.c"
goto _st18;
_st18:
p+= 1;
st_case_18:
if ( p == pe )
goto _out18;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st19;
}
goto _st0;
_st19:
p+= 1;
st_case_19:
if ( p == pe )
goto _out19;
switch( ( (*( p))) ) {
case 43: {
goto _ctr34;
}
case 45: {
goto _ctr34;
}
case 90: {
goto _ctr35;
}
}
goto _st0;
_ctr34:
{
#line 21 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
s2 = p; }
#line 443 "gen/ragel/05__datetime.c"
{
#line 22 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
z1 = p; }
#line 449 "gen/ragel/05__datetime.c"
goto _st20;
_st20:
p+= 1;
st_case_20:
if ( p == pe )
goto _out20;
if ( ( (*( p))) == 50 ) {
goto _st26;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 49 ) {
goto _st21;
}
goto _st0;
_st21:
p+= 1;
st_case_21:
if ( p == pe )
goto _out21;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st22;
}
goto _st0;
_st22:
p+= 1;
st_case_22:
if ( p == pe )
goto _out22;
if ( ( (*( p))) == 58 ) {
goto _st23;
}
goto _st0;
_st23:
p+= 1;
st_case_23:
if ( p == pe )
goto _out23;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 53 ) {
goto _st24;
}
goto _st0;
_st24:
p+= 1;
st_case_24:
if ( p == pe )
goto _out24;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st25;
}
goto _st0;
_ctr35:
{
#line 21 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
s2 = p; }
#line 505 "gen/ragel/05__datetime.c"
{
#line 22 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
z1 = p; }
#line 511 "gen/ragel/05__datetime.c"
goto _st25;
_st25:
p+= 1;
st_case_25:
if ( p == pe )
goto _out25;
if ( ( (*( p))) == 10 ) {
goto _ctr43;
}
goto _st0;
_st26:
p+= 1;
st_case_26:
if ( p == pe )
goto _out26;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 51 ) {
goto _st22;
}
goto _st0;
_ctr21:
{
#line 19 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
h1 = p; }
#line 537 "gen/ragel/05__datetime.c"
goto _st27;
_st27:
p+= 1;
st_case_27:
if ( p == pe )
goto _out27;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 51 ) {
goto _st13;
}
goto _st0;
_ctr14:
{
#line 18 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
d1 = p; }
#line 554 "gen/ragel/05__datetime.c"
goto _st28;
_st28:
p+= 1;
st_case_28:
if ( p == pe )
goto _out28;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st10;
}
goto _st0;
_ctr15:
{
#line 18 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
d1 = p; }
#line 571 "gen/ragel/05__datetime.c"
goto _st29;
_st29:
p+= 1;
st_case_29:
if ( p == pe )
goto _out29;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 49 ) {
goto _st10;
}
goto _st0;
_ctr8:
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
m1 = p; }
#line 588 "gen/ragel/05__datetime.c"
goto _st30;
_st30:
p+= 1;
st_case_30:
if ( p == pe )
goto _out30;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 50 ) {
goto _st7;
}
goto _st0;
_ctr54:
{
#line 16 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
y1 = p; }
#line 605 "gen/ragel/05__datetime.c"
goto _st31;
_st31:
p+= 1;
st_case_31:
if ( p == pe )
goto _out31;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st32;
}
goto _st0;
_st32:
p+= 1;
st_case_32:
if ( p == pe )
goto _out32;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st33;
}
goto _st0;
_st33:
p+= 1;
st_case_33:
if ( p == pe )
goto _out33;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st34;
}
goto _st0;
_st34:
p+= 1;
st_case_34:
if ( p == pe )
goto _out34;
if ( ( (*( p))) == 45 ) {
goto _ctr5;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st34;
}
goto _st0;
_out35: cs = 35; goto _out;
_out0: cs = 0; goto _out;
_out1: cs = 1; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
_out5: cs = 5; goto _out;
_out6: cs = 6; goto _out;
_out7: cs = 7; goto _out;
_out8: cs = 8; goto _out;
_out9: cs = 9; goto _out;
_out10: cs = 10; goto _out;
_out11: cs = 11; goto _out;
_out12: cs = 12; goto _out;
_out13: cs = 13; goto _out;
_out14: cs = 14; goto _out;
_out15: cs = 15; goto _out;
_out16: cs = 16; goto _out;
_out17: cs = 17; goto _out;
_out18: cs = 18; goto _out;
_out19: cs = 19; goto _out;
_out20: cs = 20; goto _out;
_out21: cs = 21; goto _out;
_out22: cs = 22; goto _out;
_out23: cs = 23; goto _out;
_out24: cs = 24; goto _out;
_out25: cs = 25; goto _out;
_out26: cs = 26; goto _out;
_out27: cs = 27; goto _out;
_out28: cs = 28; goto _out;
_out29: cs = 29; goto _out;
_out30: cs = 30; goto _out;
_out31: cs = 31; goto _out;
_out32: cs = 32; goto _out;
_out33: cs = 33; goto _out;
_out34: cs = 34; goto _out;
_out: {}
}
#line 49 "../../../benchmarks/submatch_dfa_aot/src/ragel/05__datetime.rl"
in->p = p;
in->pe = pe;
}
@@ -0,0 +1,358 @@
#line 1 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
#include "ragel/common.c"
const char *delim = "\n";
#line 26 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
#line 12 "gen/ragel/06__email.c"
static const int email_start = 9;
static const int email_first_final = 9;
static const int email_error = -1;
static const int email_en_main = 9;
#line 28 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
static void lex(Input *in, Output *out)
{
char *p = in->p;
char *pe = in->pe;
char *p1, *p2;
int cs;
#line 31 "gen/ragel/06__email.c"
{
cs = (int)email_start;
}
#line 37 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
#line 39 "gen/ragel/06__email.c"
{
switch ( cs ) {
case 9:
goto st_case_9;
case 0:
goto st_case_0;
case 1:
goto st_case_1;
case 2:
goto st_case_2;
case 3:
goto st_case_3;
case 4:
goto st_case_4;
case 5:
goto st_case_5;
case 6:
goto st_case_6;
case 7:
goto st_case_7;
case 8:
goto st_case_8;
}
_ctr10:
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
outc(out, ' ');
outs(out, p1, p2 - 1);
outc(out, ' ');
outs(out, p2, p);
outc(out, '\n');
}
#line 74 "gen/ragel/06__email.c"
goto _st9;
_st9:
p+= 1;
st_case_9:
if ( p == pe )
goto _out9;
switch( ( (*( p))) ) {
case 10: {
goto _st9;
}
case 33: {
goto _ctr12;
}
case 45: {
goto _ctr12;
}
case 61: {
goto _ctr12;
}
case 63: {
goto _ctr12;
}
}
if ( ( (*( p))) < 42 ) {
if ( 35 <= ( (*( p))) && ( (*( p))) <= 39 ) {
goto _ctr12;
}
} else if ( ( (*( p))) > 43 ) {
if ( ( (*( p))) > 57 ) {
if ( 94 <= ( (*( p))) && ( (*( p))) <= 126 ) {
goto _ctr12;
}
} else if ( ( (*( p))) >= 47 ) {
goto _ctr12;
}
} else {
goto _ctr12;
}
goto _st0;
_st0:
p+= 1;
st_case_0:
if ( p == pe )
goto _out0;
if ( ( (*( p))) == 10 ) {
goto _st9;
}
goto _st0;
_ctr12:
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
p1 = p; }
#line 129 "gen/ragel/06__email.c"
goto _st1;
_st1:
p+= 1;
st_case_1:
if ( p == pe )
goto _out1;
switch( ( (*( p))) ) {
case 10: {
goto _st9;
}
case 33: {
goto _st1;
}
case 46: {
goto _st2;
}
case 61: {
goto _st1;
}
case 63: {
goto _st1;
}
case 64: {
goto _st3;
}
}
if ( ( (*( p))) < 42 ) {
if ( 35 <= ( (*( p))) && ( (*( p))) <= 39 ) {
goto _st1;
}
} else if ( ( (*( p))) > 43 ) {
if ( ( (*( p))) > 57 ) {
if ( 94 <= ( (*( p))) && ( (*( p))) <= 126 ) {
goto _st1;
}
} else if ( ( (*( p))) >= 45 ) {
goto _st1;
}
} else {
goto _st1;
}
goto _st0;
_st2:
p+= 1;
st_case_2:
if ( p == pe )
goto _out2;
switch( ( (*( p))) ) {
case 10: {
goto _st9;
}
case 33: {
goto _st1;
}
case 45: {
goto _st1;
}
case 61: {
goto _st1;
}
case 63: {
goto _st1;
}
}
if ( ( (*( p))) < 42 ) {
if ( 35 <= ( (*( p))) && ( (*( p))) <= 39 ) {
goto _st1;
}
} else if ( ( (*( p))) > 43 ) {
if ( ( (*( p))) > 57 ) {
if ( 94 <= ( (*( p))) && ( (*( p))) <= 126 ) {
goto _st1;
}
} else if ( ( (*( p))) >= 47 ) {
goto _st1;
}
} else {
goto _st1;
}
goto _st0;
_st3:
p+= 1;
st_case_3:
if ( p == pe )
goto _out3;
if ( ( (*( p))) == 10 ) {
goto _st9;
}
if ( ( (*( p))) > 57 ) {
if ( 97 <= ( (*( p))) && ( (*( p))) <= 122 ) {
goto _ctr5;
}
} else if ( ( (*( p))) >= 48 ) {
goto _ctr5;
}
goto _st0;
_ctr5:
{
#line 16 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
p2 = p; }
#line 232 "gen/ragel/06__email.c"
goto _st4;
_st4:
p+= 1;
st_case_4:
if ( p == pe )
goto _out4;
switch( ( (*( p))) ) {
case 10: {
goto _st9;
}
case 45: {
goto _st5;
}
case 46: {
goto _st6;
}
}
if ( ( (*( p))) > 57 ) {
if ( 97 <= ( (*( p))) && ( (*( p))) <= 122 ) {
goto _st4;
}
} else if ( ( (*( p))) >= 48 ) {
goto _st4;
}
goto _st0;
_st5:
p+= 1;
st_case_5:
if ( p == pe )
goto _out5;
switch( ( (*( p))) ) {
case 10: {
goto _st9;
}
case 45: {
goto _st5;
}
}
if ( ( (*( p))) > 57 ) {
if ( 97 <= ( (*( p))) && ( (*( p))) <= 122 ) {
goto _st4;
}
} else if ( ( (*( p))) >= 48 ) {
goto _st4;
}
goto _st0;
_st6:
p+= 1;
st_case_6:
if ( p == pe )
goto _out6;
if ( ( (*( p))) == 10 ) {
goto _st9;
}
if ( ( (*( p))) > 57 ) {
if ( 97 <= ( (*( p))) && ( (*( p))) <= 122 ) {
goto _st7;
}
} else if ( ( (*( p))) >= 48 ) {
goto _st7;
}
goto _st0;
_st7:
p+= 1;
st_case_7:
if ( p == pe )
goto _out7;
switch( ( (*( p))) ) {
case 10: {
goto _ctr10;
}
case 45: {
goto _st8;
}
case 46: {
goto _st6;
}
}
if ( ( (*( p))) > 57 ) {
if ( 97 <= ( (*( p))) && ( (*( p))) <= 122 ) {
goto _st7;
}
} else if ( ( (*( p))) >= 48 ) {
goto _st7;
}
goto _st0;
_st8:
p+= 1;
st_case_8:
if ( p == pe )
goto _out8;
switch( ( (*( p))) ) {
case 10: {
goto _st9;
}
case 45: {
goto _st8;
}
}
if ( ( (*( p))) > 57 ) {
if ( 97 <= ( (*( p))) && ( (*( p))) <= 122 ) {
goto _st7;
}
} else if ( ( (*( p))) >= 48 ) {
goto _st7;
}
goto _st0;
_out9: cs = 9; goto _out;
_out0: cs = 0; goto _out;
_out1: cs = 1; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
_out5: cs = 5; goto _out;
_out6: cs = 6; goto _out;
_out7: cs = 7; goto _out;
_out8: cs = 8; goto _out;
_out: {}
}
#line 38 "../../../benchmarks/submatch_dfa_aot/src/ragel/06__email.rl"
in->p = p;
in->pe = pe;
}
@@ -0,0 +1,321 @@
#line 1 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
#include "ragel/common.c"
const char *delim = "\n";
#line 27 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
#line 12 "gen/ragel/07__ipv4.c"
static const int ipv4_start = 16;
static const int ipv4_first_final = 16;
static const int ipv4_error = 0;
static const int ipv4_en_main = 16;
#line 29 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
static void lex(Input *in, Output *out)
{
char *p = in->p;
char *pe = in->pe;
const char *p1, *p2, *p3, *p4;
int cs;
#line 31 "gen/ragel/07__ipv4.c"
{
cs = (int)ipv4_start;
}
#line 38 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
#line 39 "gen/ragel/07__ipv4.c"
{
switch ( cs ) {
case 16:
goto st_case_16;
case 0:
goto st_case_0;
case 1:
goto st_case_1;
case 2:
goto st_case_2;
case 3:
goto st_case_3;
case 4:
goto st_case_4;
case 5:
goto st_case_5;
case 6:
goto st_case_6;
case 7:
goto st_case_7;
case 8:
goto st_case_8;
case 9:
goto st_case_9;
case 10:
goto st_case_10;
case 11:
goto st_case_11;
case 12:
goto st_case_12;
case 13:
goto st_case_13;
case 14:
goto st_case_14;
case 15:
goto st_case_15;
}
_ctr14:
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
outs(out, p1, p2 - 1);
outc(out, ',');
outs(out, p2, p3 - 1);
outc(out, ',');
outs(out, p3, p4 - 1);
outc(out, ',');
outs(out, p4, p);
outc(out, '\n');
}
#line 91 "gen/ragel/07__ipv4.c"
goto _st16;
_st16:
p+= 1;
st_case_16:
if ( p == pe )
goto _out16;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr21;
}
goto _st0;
_st0:
st_case_0:
goto _out0;
_ctr21:
{
#line 11 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
p1 = p; }
#line 111 "gen/ragel/07__ipv4.c"
goto _st1;
_st1:
p+= 1;
st_case_1:
if ( p == pe )
goto _out1;
if ( ( (*( p))) == 46 ) {
goto _st2;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st14;
}
goto _st0;
_st2:
p+= 1;
st_case_2:
if ( p == pe )
goto _out2;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr4;
}
goto _st0;
_ctr4:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
p2 = p; }
#line 140 "gen/ragel/07__ipv4.c"
goto _st3;
_st3:
p+= 1;
st_case_3:
if ( p == pe )
goto _out3;
if ( ( (*( p))) == 46 ) {
goto _st4;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st12;
}
goto _st0;
_st4:
p+= 1;
st_case_4:
if ( p == pe )
goto _out4;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr8;
}
goto _st0;
_ctr8:
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
p3 = p; }
#line 169 "gen/ragel/07__ipv4.c"
goto _st5;
_st5:
p+= 1;
st_case_5:
if ( p == pe )
goto _out5;
if ( ( (*( p))) == 46 ) {
goto _st6;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st10;
}
goto _st0;
_st6:
p+= 1;
st_case_6:
if ( p == pe )
goto _out6;
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _ctr12;
}
goto _st0;
_ctr12:
{
#line 14 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
p4 = p; }
#line 198 "gen/ragel/07__ipv4.c"
goto _st7;
_st7:
p+= 1;
st_case_7:
if ( p == pe )
goto _out7;
if ( ( (*( p))) == 10 ) {
goto _ctr14;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st8;
}
goto _st0;
_st8:
p+= 1;
st_case_8:
if ( p == pe )
goto _out8;
if ( ( (*( p))) == 10 ) {
goto _ctr14;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st9;
}
goto _st0;
_st9:
p+= 1;
st_case_9:
if ( p == pe )
goto _out9;
if ( ( (*( p))) == 10 ) {
goto _ctr14;
}
goto _st0;
_st10:
p+= 1;
st_case_10:
if ( p == pe )
goto _out10;
if ( ( (*( p))) == 46 ) {
goto _st6;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st11;
}
goto _st0;
_st11:
p+= 1;
st_case_11:
if ( p == pe )
goto _out11;
if ( ( (*( p))) == 46 ) {
goto _st6;
}
goto _st0;
_st12:
p+= 1;
st_case_12:
if ( p == pe )
goto _out12;
if ( ( (*( p))) == 46 ) {
goto _st4;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st13;
}
goto _st0;
_st13:
p+= 1;
st_case_13:
if ( p == pe )
goto _out13;
if ( ( (*( p))) == 46 ) {
goto _st4;
}
goto _st0;
_st14:
p+= 1;
st_case_14:
if ( p == pe )
goto _out14;
if ( ( (*( p))) == 46 ) {
goto _st2;
}
if ( 48 <= ( (*( p))) && ( (*( p))) <= 57 ) {
goto _st15;
}
goto _st0;
_st15:
p+= 1;
st_case_15:
if ( p == pe )
goto _out15;
if ( ( (*( p))) == 46 ) {
goto _st2;
}
goto _st0;
_out16: cs = 16; goto _out;
_out0: cs = 0; goto _out;
_out1: cs = 1; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
_out5: cs = 5; goto _out;
_out6: cs = 6; goto _out;
_out7: cs = 7; goto _out;
_out8: cs = 8; goto _out;
_out9: cs = 9; goto _out;
_out10: cs = 10; goto _out;
_out11: cs = 11; goto _out;
_out12: cs = 12; goto _out;
_out13: cs = 13; goto _out;
_out14: cs = 14; goto _out;
_out15: cs = 15; goto _out;
_out: {}
}
#line 39 "../../../benchmarks/submatch_dfa_aot/src/ragel/07__ipv4.rl"
in->p = p;
in->pe = pe;
}
@@ -0,0 +1,201 @@
#line 1 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
#include <assert.h>
#include "ragel/common.c"
const char *delim = "\n";
#line 22 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
#line 13 "gen/ragel/10__alt1_2.c"
static const int m_start = 3;
static const int m_first_final = 3;
static const int m_error = 0;
static const int m_en_main = 3;
#line 24 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
static void lex(Input *in, Output *out)
{
char *p = in->p;
char *pe = in->pe;
const char
*a1, *b1,
*a2, *b2;
int cs;
#line 34 "gen/ragel/10__alt1_2.c"
{
cs = (int)m_start;
}
#line 35 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
#line 42 "gen/ragel/10__alt1_2.c"
{
switch ( cs ) {
case 3:
goto st_case_3;
case 0:
goto st_case_0;
case 1:
goto st_case_1;
case 2:
goto st_case_2;
}
_ctr2:
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
a2 = p; b1 = b2 = NULL; }
#line 59 "gen/ragel/10__alt1_2.c"
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
outc(out, '\n');
}
#line 69 "gen/ragel/10__alt1_2.c"
goto _st3;
_ctr4:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
b2 = p; a1 = a2 = NULL; }
#line 77 "gen/ragel/10__alt1_2.c"
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
outc(out, '\n');
}
#line 87 "gen/ragel/10__alt1_2.c"
goto _st3;
_ctr6:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
b1 = p; }
#line 95 "gen/ragel/10__alt1_2.c"
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
b2 = p; a1 = a2 = NULL; }
#line 101 "gen/ragel/10__alt1_2.c"
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
a1 = p; }
#line 107 "gen/ragel/10__alt1_2.c"
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
a2 = p; b1 = b2 = NULL; }
#line 113 "gen/ragel/10__alt1_2.c"
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
outc(out, '\n');
}
#line 123 "gen/ragel/10__alt1_2.c"
goto _st3;
_st3:
p+= 1;
st_case_3:
if ( p == pe )
goto _out3;
switch( ( (*( p))) ) {
case 10: {
goto _ctr6;
}
case 97: {
goto _ctr7;
}
case 98: {
goto _ctr8;
}
}
goto _st0;
_st0:
st_case_0:
goto _out0;
_ctr7:
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
a1 = p; }
#line 151 "gen/ragel/10__alt1_2.c"
goto _st1;
_st1:
p+= 1;
st_case_1:
if ( p == pe )
goto _out1;
switch( ( (*( p))) ) {
case 10: {
goto _ctr2;
}
case 97: {
goto _st1;
}
}
goto _st0;
_ctr8:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
b1 = p; }
#line 173 "gen/ragel/10__alt1_2.c"
goto _st2;
_st2:
p+= 1;
st_case_2:
if ( p == pe )
goto _out2;
switch( ( (*( p))) ) {
case 10: {
goto _ctr4;
}
case 98: {
goto _st2;
}
}
goto _st0;
_out3: cs = 3; goto _out;
_out0: cs = 0; goto _out;
_out1: cs = 1; goto _out;
_out2: cs = 2; goto _out;
_out: {}
}
#line 36 "../../../benchmarks/submatch_dfa_aot/src/ragel/10__alt1_2.rl"
in->p = p;
in->pe = pe;
}
@@ -0,0 +1,327 @@
#line 1 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
#include <assert.h>
#include "ragel/common.c"
const char *delim = "\n";
#line 26 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
#line 13 "gen/ragel/11__alt1_4.c"
static const int m_start = 5;
static const int m_first_final = 5;
static const int m_error = 0;
static const int m_en_main = 5;
#line 28 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
static void lex(Input *in, Output *out)
{
char *p = in->p;
char *pe = in->pe;
const char
*a1, *b1, *c1, *d1,
*a2, *b2, *c2, *d2;
int cs;
#line 34 "gen/ragel/11__alt1_4.c"
{
cs = (int)m_start;
}
#line 39 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
#line 42 "gen/ragel/11__alt1_4.c"
{
switch ( cs ) {
case 5:
goto st_case_5;
case 0:
goto st_case_0;
case 1:
goto st_case_1;
case 2:
goto st_case_2;
case 3:
goto st_case_3;
case 4:
goto st_case_4;
}
_ctr2:
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
a2 = p; b1 = b2 = c1 = c2 = d1 = d2 = NULL; }
#line 63 "gen/ragel/11__alt1_4.c"
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
else if (c1) { outc(out, 'C'); outs(out, c1, c2); }
else if (d1) { outc(out, 'D'); outs(out, d1, d2); }
outc(out, '\n');
}
#line 75 "gen/ragel/11__alt1_4.c"
goto _st5;
_ctr4:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
b2 = p; a1 = a2 = c1 = c2 = d1 = d2 = NULL; }
#line 83 "gen/ragel/11__alt1_4.c"
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
else if (c1) { outc(out, 'C'); outs(out, c1, c2); }
else if (d1) { outc(out, 'D'); outs(out, d1, d2); }
outc(out, '\n');
}
#line 95 "gen/ragel/11__alt1_4.c"
goto _st5;
_ctr6:
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
c2 = p; a1 = a2 = b1 = b2 = d1 = d2 = NULL; }
#line 103 "gen/ragel/11__alt1_4.c"
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
else if (c1) { outc(out, 'C'); outs(out, c1, c2); }
else if (d1) { outc(out, 'D'); outs(out, d1, d2); }
outc(out, '\n');
}
#line 115 "gen/ragel/11__alt1_4.c"
goto _st5;
_ctr8:
{
#line 14 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
d2 = p; a1 = a2 = b1 = b2 = c1 = c2 = NULL; }
#line 123 "gen/ragel/11__alt1_4.c"
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
else if (c1) { outc(out, 'C'); outs(out, c1, c2); }
else if (d1) { outc(out, 'D'); outs(out, d1, d2); }
outc(out, '\n');
}
#line 135 "gen/ragel/11__alt1_4.c"
goto _st5;
_ctr10:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
b1 = p; }
#line 143 "gen/ragel/11__alt1_4.c"
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
b2 = p; a1 = a2 = c1 = c2 = d1 = d2 = NULL; }
#line 149 "gen/ragel/11__alt1_4.c"
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
c1 = p; }
#line 155 "gen/ragel/11__alt1_4.c"
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
c2 = p; a1 = a2 = b1 = b2 = d1 = d2 = NULL; }
#line 161 "gen/ragel/11__alt1_4.c"
{
#line 14 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
d1 = p; }
#line 167 "gen/ragel/11__alt1_4.c"
{
#line 14 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
d2 = p; a1 = a2 = b1 = b2 = c1 = c2 = NULL; }
#line 173 "gen/ragel/11__alt1_4.c"
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
a1 = p; }
#line 179 "gen/ragel/11__alt1_4.c"
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
a2 = p; b1 = b2 = c1 = c2 = d1 = d2 = NULL; }
#line 185 "gen/ragel/11__alt1_4.c"
{
#line 17 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
if (a1) { outc(out, 'A'); outs(out, a1, a2); }
else if (b1) { outc(out, 'B'); outs(out, b1, b2); }
else if (c1) { outc(out, 'C'); outs(out, c1, c2); }
else if (d1) { outc(out, 'D'); outs(out, d1, d2); }
outc(out, '\n');
}
#line 197 "gen/ragel/11__alt1_4.c"
goto _st5;
_st5:
p+= 1;
st_case_5:
if ( p == pe )
goto _out5;
switch( ( (*( p))) ) {
case 10: {
goto _ctr10;
}
case 97: {
goto _ctr11;
}
case 98: {
goto _ctr12;
}
case 99: {
goto _ctr13;
}
case 100: {
goto _ctr14;
}
}
goto _st0;
_st0:
st_case_0:
goto _out0;
_ctr11:
{
#line 15 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
a1 = p; }
#line 231 "gen/ragel/11__alt1_4.c"
goto _st1;
_st1:
p+= 1;
st_case_1:
if ( p == pe )
goto _out1;
switch( ( (*( p))) ) {
case 10: {
goto _ctr2;
}
case 97: {
goto _st1;
}
}
goto _st0;
_ctr12:
{
#line 12 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
b1 = p; }
#line 253 "gen/ragel/11__alt1_4.c"
goto _st2;
_st2:
p+= 1;
st_case_2:
if ( p == pe )
goto _out2;
switch( ( (*( p))) ) {
case 10: {
goto _ctr4;
}
case 98: {
goto _st2;
}
}
goto _st0;
_ctr13:
{
#line 13 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
c1 = p; }
#line 275 "gen/ragel/11__alt1_4.c"
goto _st3;
_st3:
p+= 1;
st_case_3:
if ( p == pe )
goto _out3;
switch( ( (*( p))) ) {
case 10: {
goto _ctr6;
}
case 99: {
goto _st3;
}
}
goto _st0;
_ctr14:
{
#line 14 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
d1 = p; }
#line 297 "gen/ragel/11__alt1_4.c"
goto _st4;
_st4:
p+= 1;
st_case_4:
if ( p == pe )
goto _out4;
switch( ( (*( p))) ) {
case 10: {
goto _ctr8;
}
case 100: {
goto _st4;
}
}
goto _st0;
_out5: cs = 5; goto _out;
_out0: cs = 0; goto _out;
_out1: cs = 1; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
_out: {}
}
#line 40 "../../../benchmarks/submatch_dfa_aot/src/ragel/11__alt1_4.rl"
in->p = p;
in->pe = pe;
}
Loaded 100 of 5046 files, more files were not shown because too many files have changed in this diff. Show more