Compare commits

..
741 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
4068 changed files with 1964457 additions and 832392 deletions
+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
+19 -2
View File
@@ -1,4 +1,22 @@
autom4te.cache/
# 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
@@ -9,6 +27,5 @@ config.sub
depcomp
install-sh
ltmain.sh
m4/
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
+4 -1
View File
@@ -1,5 +1,8 @@
language: cpp
# use Ubuntu 20.04 (Focal Fossa) that defaults to Python 3
dist: focal
# speed up incremental builds
cache: ccache
@@ -75,7 +78,7 @@ script:
- make -j$(nproc)
- |
if [ x${SKELETON} = "xyes" ]; then
./run_tests.sh --skeleton
./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.
+331
View File
@@ -1,10 +1,341 @@
Changelog
=========
----
3.0x
----
3.1 (2023-07-19)
~~~~~~~~~~~~~~~~
- Added capturing groups with leftmost greedy semantics:
+ Enabled with ``--leftmost-captures`` option or ``re2c:leftmost_captures``
configuration
(`55de79d8 <https://github.com/skvadrik/re2c/commit/55de79d8>`_,
`3a98b543 <https://github.com/skvadrik/re2c/commit/3a98b543>`_).
- Added non-capturing groups:
+ Added new syntax ``(! ...)`` for non-capturing groups
(`1edd25d3 <https://github.com/skvadrik/re2c/commit/1edd25d3>`_,
`b813c9b4 <https://github.com/skvadrik/re2c/commit/b813c9b4>`_,
`338806b9 <https://github.com/skvadrik/re2c/commit/338806b9>`_).
+ Added the ability to flip defaults: make ``(...)`` capturing and ``(! ...)``
non-capturing with ``--invert-captures`` option or ``re2c:invert_captures``
configuration
(`20030ff1 <https://github.com/skvadrik/re2c/commit/20030ff1>`_,
`ce756195 <https://github.com/skvadrik/re2c/commit/ce756195>`_).
- Regenerated Unicode include header to support a newer standard
(`e3ec2597 <https://github.com/skvadrik/re2c/commit/e3ec2597>`_).
- Published TDFA paper: https://arxiv.org/abs/2206.01398, co-authored with
Angelo Borsotti
(`fa94d9c7 <https://github.com/skvadrik/re2c/commit/fa94d9c7>`_).
- Removed experimental algorithms that are superseded by TDFA(1) and
generally less efficient:
+ Removed staDFA algorithm and deprecated ``--stadfa`` option
(`ac5c06cc <https://github.com/skvadrik/re2c/commit/ac5c06cc>`_).
+ Removed TDFA(0) algorithm and deprecated ``--no-lookahead`` option
(`dc8f264a <https://github.com/skvadrik/re2c/commit/dc8f264a>`_).
+ (libre2c) Removed backward-matching algorithm
(`27256be1 <https://github.com/skvadrik/re2c/commit/27256be1>`_).
+ (libre2c) Removed Kuklewicz POSIX disambiguation algorithm
(`aa97b014 <https://github.com/skvadrik/re2c/commit/aa97b014>`_).
+ (libre2c) Removed GTOP shortest path finding algorithm
(`511a030c <https://github.com/skvadrik/re2c/commit/511a030c>`_).
- Bug fixes:
+ Fixed parsing of raw UTF-8 characters in Flex compatibility mode
(`d87f86ed <https://github.com/skvadrik/re2c/commit/d87f86ed>`_).
+ Added header file to the dependencies generated with ``--depfile`` option
(`f807f763 <https://github.com/skvadrik/re2c/commit/f807f763>`_
and `2dda36aa <https://github.com/skvadrik/re2c/commit/2dda36aa>`_).
+ Fixed stack overflow on large regular expressions by rewriting recursive
functions in iterative form
(`46a9b4c4 <https://github.com/skvadrik/re2c/commit/46a9b4c4>`_,
`aaf68292 <https://github.com/skvadrik/re2c/commit/aaf68292>`_,
`02e5d797 <https://github.com/skvadrik/re2c/commit/02e5d797>`_,
`5fffb187 <https://github.com/skvadrik/re2c/commit/5fffb187>`_)
and limited stack to 256K on GithubActions CI
(`111ee5da <https://github.com/skvadrik/re2c/commit/111ee5da>`_).
- Build system:
+ Added minimal http://bazel.build integration
(`3205c867 <https://github.com/skvadrik/re2c/commit/3205c867>`_).
+ Added configure option ``--enable-parsers`` that regenerates bison parsers
(`9e0dbd3c <https://github.com/skvadrik/re2c/commit/9e0dbd3c>`_).
+ Added CMake option ``RE2C_REBUILD_PARSERS``
(`6e91c22d <https://github.com/skvadrik/re2c/commit/6e91c22d>`_).
+ With CMake, fixed documentation generation on Windows.
- Codebase improvements:
+ Moved the entire codebase to C++11.
+ Added uniform error handling (return codes are now properly checked and
returned to the caller).
+ Reorganized codegen subsystem in four well-defined phases (analyze,
generate, fixup, render) and separated codegen from parsing phase.
+ Improved memory allocation by using slab allocators instead of global free
lists.
+ Moved to pure API for bison parsers.
+ Unified code style.
- Testing:
+ Added ``--verbose`` flag to run_tests.py and suppressed verbose output by
default.
+ Multiple improvements of continuous testing with GithubActions.
3.0 (2022-01-27)
~~~~~~~~~~~~~~~~
- Added code generation backend for Rust:
+ Enabled with ``--lang rust`` option.
+ A new ``re2rust`` binary (built by default, or configured with
``--enable-rust`` Autoconf option and ``RE2C_BUILD_RE2RUST`` CMake option).
- Added options:
+ ``--loop-switch``
+ ``--no-unsafe``
- Added configurations;
+ ``re2c:label:yyloop``
+ ``re2c:unsafe``
- Renamed options to use common naming scheme. The old names are supported as
aliases, so the change does not break existing code. Documentation has been
updated to use new names.
+ ``--api`` is a new alias for ``--input``
+ ``--ebcdic`` is a new alias for ``--ecb``
+ ``--ucs2`` is a new alias for ``--wide-chars``
+ ``--utf32`` is a new alias for ``--unicode``
+ ``--utf16`` is a new alias for ``--utf-16``
+ ``--utf8`` is a new alias for ``--utf-8``
+ ``--header`` is a new alias for ``--type-header``
- Renamed configurations to use common naming scheme and support proper scoping
under subcategories such as ``:define``, ``:label``, ``:variable``, etc. The
old names are supported as aliases, so the change does not break existing
code. Documentation has been updated to use new names.
+ ``re2c:api`` is a new alias for ``re2c:flags:input``
+ ``re2c:bit-vectors`` is a new alias for ``re2c:flags:bit-vectors``
+ ``re2c:case-insensitive`` is a new alias for ``re2c:flags:case-insensitive``
+ ``re2c:case-inverted`` is a new alias for ``re2c:flags:case-inverted``
+ ``re2c:case-ranges`` is a new alias for ``re2c:flags:case-ranges``
+ ``re2c:cond:prefix`` is a new alias for ``re2c:condprefix``
+ ``re2c:cond:enumprefix`` is a new alias for ``re2c:condenumprefix``
+ ``re2c:computed-gotos`` is a new alias for ``re2c:flags:computed-gotos``
+ ``re2c:computed-gotos:threshold`` is a new alias for ``re2c:cgoto:threshold``
+ ``re2c:debug-output`` is a new alias for ``re2c:flags:debug-output``
+ ``re2c:encoding:ebcdic`` is a new alias for ``re2c:flags:ecb``
+ ``re2c:encoding:utf32`` is a new alias for ``re2c:flags:unicode``
+ ``re2c:encoding:ucs2`` is a new alias for ``re2c:flags:wide-chars``
+ ``re2c:encoding:utf16`` is a new alias for ``re2c:flags:utf-16``
+ ``re2c:encoding:utf8`` is a new alias for ``re2c:flags:utf-8``
+ ``re2c:encoding-policy`` is a new alias for ``re2c:flags:encoding-policy``
+ ``re2c:empty-class`` is a new alias for ``re2c:flags:empty-class``
+ ``re2c:header`` is a new alias for ``re2c:flags:type-header``
+ ``re2c:label:prefix`` is a new alias for ``re2c:labelprefix``
+ ``re2c:label:yyfill`` is a new alias for ``re2c:label:yyFillLabel``
+ ``re2c:label:start`` is a new alias for ``re2c:startlabel``
+ ``re2c:nested-ifs`` is a new alias for ``re2c:flags:nested-ifs``
+ ``re2c:posix-captures`` is a new alias for ``re2c:flags:posix-captures``
+ ``re2c:tags`` is a new alias for ``re2c:flags:tags``
+ ``re2c:variable:yych:conversion`` is a new alias for ``re2c:yych:conversion``
+ ``re2c:variable:yych:emit`` is a new alias for ``re2c:yych:emit``
+ ``re2c:variable:yybm:hex`` is a new alias for ``re2c:yybm:hex``
+ ``re2c:unsafe`` is a new alias for ``re2c:flags:unsafe``
- Added directive alias ``conditions:re2c`` for ``types:re2c``.
- Multiple small changes in code generation, including some formatting changes
that result in large diffs in the generated code:
+ Do not allocate indices for unused state labels (this results in a change in
state enumeration), commits
`919570c4 <https://github.com/skvadrik/re2c/commit/919570c4>`_ and
`82b704f6 <https://github.com/skvadrik/re2c/commit/82b704f6>`_.
+ Do not generate redundant ``YYPEEK`` statements, commit
`cca31d22 <https://github.com/skvadrik/re2c/commit/cca31d22>`_.
+ Do not generate ``YYDEBUG`` statements for unused states labels, commit
`a46f01e6 <https://github.com/skvadrik/re2c/commit/a46f01e6>`_.
+ C backend: change formatting of switch statements, commit
`ed88e12e <https://github.com/skvadrik/re2c/commit/ed88e12e>`_.
+ Go backend: render continuous character ranges in compact form, commit
`09161b14 <https://github.com/skvadrik/re2c/commit/09161b14>`_.
+ Mark start and end of included .re files with line directives, commit
`48e83fca <https://github.com/skvadrik/re2c/commit/48e83fca>`_.
- A fix to limit maximum allowed NFA and DFA size (to avoid out of memory
crashes and stack overflows), commit
`a3473fd7 <https://github.com/skvadrik/re2c/commit/a3473fd7>`_.
- A fix to correctly compute fixed tags in trailing context, commit
`68e1ab71 <https://github.com/skvadrik/re2c/commit/68e1ab71>`_.
- A fix to generate non-overlapping names for s-tag and m-tag variables, commit
`7c6b5c95 <https://github.com/skvadrik/re2c/commit/7c6b5c95>`_.
- Infrastructural: added support for CMake presets.
- Updated documentation.
- Backwards-incompatible changes that are unlikely to affect any users:
+ Restrict lexical contexts where ``%{`` is recognized as a block start,
commit `dba7d055 <https://github.com/skvadrik/re2c/commit/dba7d055>`_.
+ Emit an error when repetition lower bound exceeds upper bound, commit
`039c1894 <https://github.com/skvadrik/re2c/commit/039c1894>`_.
----
2.2x
----
2.2 (2021-08-01)
~~~~~~~~~~~~~~~~
- Added named blocks and block lists in directives.
- Added local blocks ``/*!local:re2c ... */``.
- Added in-block ``!include`` directive.
- Added in-block ``!use`` directive.
- Allowed reusable blocks without ``-r --reusable`` option.
- Allowed customizing the generated code with configurations for directives
``max:re2c``, ``maxnmatch:re2c``, ``stags:re2c``, ``mtags:re2c`` and
``types:re2c`` (see directive descriptions for details).
- Forbid arbitrary text at the end of ``max:re2c`` directive. This may break
backwards compatibility, although it is unlikely that this was used by anyone.
The change was necessary in order to allow customization of the generated code
with configurations.
- Deprecated configurations ``flags:i``, ``flags:no-debug-info`` in favour of
the global options ``-i``, ``--no-debug-info``.
- Reimplemented re2c test runner in Python (thanks to
`Serghei Iakovlev <https://github.com/sergeyklay>`_). Improved integration
with GitHub Actions.
- Changes in the experimental libre2c library: added new algorithms that
construct t-string or extract submatch on all repetitions; added TDFA
benchmark written in Java by Angelo Borsotti.
- Updated documentation.
----
2.1x
----
2.1.1 (2021-03-27)
~~~~~~~~~~~~~~~~~~
- Added missing CMakeLists.txt to release tarballs
(`#346 <https://github.com/skvadrik/re2c/issues/346>`_).
2.1 (2021-03-26)
~~~~~~~~~~~~~~~~
- Added GitHub Actions CI for Linux, macOS and Windows and fixed numerous build
issues on those platforms (thanks to
`Serghei Iakovlev <https://github.com/sergeyklay>`_).
- Added benchmarks for submatch extraction in lexer generators (ragel vs.
kleenex vs. re2c with TDFA(0), TDFA(1) or sta-DFA algorithms).
+ New Autotools (configure) options: ``--enable-benchmarks``,
``--enable-benchmarks-regenerate``
+ New CMake options: ``-DRE2C_BUILD_BENCHMARKS``, ``-DRE2C_REGEN_BENCHMARKS``
+ New `json2pgfplot.py
<https://github.com/skvadrik/re2c/blob/master/benchmarks/json2pgfplot.py>`_
script that converts benchmark results in JSON to a PDF with bar charts
- Added option ``--depfile <filename>`` to generate build dependency files
(allows to track ``/*!include:re2c*/`` dependencies in the build system).
- Added option ``--fixed-tags <none | all | toplevel>`` and improved fixed-tag
optimization to work with nested tags.
- Added lzip to the distribution tarballs.
- Added registerless-TDFA algorithm in the experimental libre2c library.
- Explicitly disallowed invalid configuration when ``-f``, ``--storable-state``
option is used, but ``YYFILL`` is disabled
(`#306 <https://github.com/skvadrik/re2c/issues/306>`_).
- Fixed bug in UTF-8 decode for 4-bytes rune
(`#307 <https://github.com/skvadrik/re2c/pull/307>`_, thanks to
`Satoshi Yasushima <https://github.com/s-yasu>`_).
- Fixed bugs in rare cases of the end-of-input rule ``$`` usage
(`277f0295 <https://github.com/skvadrik/re2c/commit/277f0295fc77a2dad3b9838e45f787319b54a25f>`_,
`68611a57 <https://github.com/skvadrik/re2c/commit/68611a57a9683c05801255b35ba6217b91391dd8>`_
and `a9d582f9 <https://github.com/skvadrik/re2c/commit/a9d582f9d2a6d123aa55f3b8b73076aae7cb5616>`_).
- Optimized ``--skeleton`` generation time.
- Renamed internal option ``--dfa`` to ``--nested-negative-tags``.
- Updated documentation for end of input handling and submatch extraction.
----
2.0x
----
2.0.3 (2020-08-22)
~~~~~~~~~~~~~~~~~~
- Fix issues when building re2c as a CMake subproject
(`#302 <https://github.com/skvadrik/re2c/pull/302>`_:
Using CMake add_subdirectory fails)
- Final corrections in the SIMPA article "RE2C: A lexer generator based on
lookahead-TDFA", https://doi.org/10.1016/j.simpa.2020.100027
2.0.2 (2020-08-08)
~~~~~~~~~~~~~~~~~~
- Enable re2go building by default.
- Package CMake files into release tarball.
2.0.1 (2020-07-29)
~~~~~~~~~~~~~~~~~~
- Updated version for CMake build system (forgotten in release 2.0).
- Added a short article about re2c for the Software Impacts journal.
2.0 (2020-07-20)
~~~~~~~~~~~~~~~~
+232 -214
View File
@@ -1,65 +1,61 @@
cmake_minimum_required(VERSION 3.12)
project(re2c VERSION 1.3 HOMEPAGE_URL "https://re2c.org/")
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(Re2cTryCXXFlag)
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 "need RE2C_FOR_BUILD for RE2C_REBUILD_LEXERS")
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)
find_program(RST2MAN NAMES rst2man rst2man.py)
if(NOT RST2MAN)
message(FATAL_ERROR "need rst2man or rst2man.py for 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()
option(RE2C_BUILD_LIBS "Build libraries" OFF)
# checks for programs
find_package(BISON)
# checks for C++ compiler flags
set(CMAKE_CXX_STANDARD 98)
set(CMAKE_CXX_EXTENSIONS OFF)
# 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
if(NOT CMAKE_BUILD_TYPE)
try_cxxflag("-O2")
endif()
try_cxxflag("-W")
try_cxxflag("-Wall")
try_cxxflag("-Wextra")
try_cxxflag("-Weffc++")
try_cxxflag("-pedantic")
try_cxxflag("-Wformat=2")
try_cxxflag("-Wredundant-decls")
try_cxxflag("-Wsuggest-attribute=format")
try_cxxflag("-Wconversion")
try_cxxflag("-Wsign-conversion")
try_cxxflag("-Werror=return-type")
try_cxxflag("-Weverything"
"-Wno-unknown-warning-option" # CLANG eats some GCC options only to warn they are unknown
"-Wno-reserved-id-macro" # to allow header guards of the form '_RE2C_PATH_TO_HEADER_BASENAME_'
"-Wno-padded"
"-Wno-old-style-cast" # RE2C-generated lexer has lots of C-syle casts because of 're2c:yych:conversion = 1;'
"-Wno-nested-anon-types"
"-Wno-global-constructors" # initialization of global constants with std::numeric_limits<...> (mostly for size_t)
"-Wno-shadow-field-in-constructor" # using same names in ctor seems more like a feature
"-Wno-undefined-func-template" # explicit specialization to reduce build dependencies
)
try_cxxflag("-fdiagnostics-color=always")
# use system stdint.h if present, otherwise fallback to src/c99_stdint.h
ac_check_headers("stdint.h")
# needed for POSIX file API
ac_check_headers("sys/types.h")
ac_check_headers("sys/stat.h")
@@ -68,42 +64,36 @@ ac_check_headers("unistd.h")
# windows POSIX-like API
ac_check_headers("io.h")
# list of possible types to use in typedefs
ac_check_sizeof("char")
ac_check_sizeof("short")
ac_check_sizeof("int")
ac_check_sizeof("long")
ac_check_sizeof("long long")
ac_check_sizeof("__int64")
ac_check_sizeof("void *")
# 64-bit integer constant suffix
ac_check_sizeof("0l")
ac_check_sizeof("0ll")
ac_check_sizeof("0i8")
# 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_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_help "${CMAKE_CURRENT_BINARY_DIR}/src/msg/help.cc")
set(re2c_genhelp "${CMAKE_CURRENT_SOURCE_DIR}/build/gen_help.sh")
set(re2c_splitman "${CMAKE_CURRENT_SOURCE_DIR}/build/split_man.sh")
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.sh.in run_tests.sh @ONLY)
set(RE2C_RUN_TESTS "${CMAKE_CURRENT_BINARY_DIR}/run_tests.sh")
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()
@@ -136,21 +126,16 @@ add_library(re2c_objects_autogen_ver_to_vernum OBJECT
)
set(re2c_sources
src/codegen/code_goto.cc
src/codegen/combine.cc
src/codegen/gen_bitmaps.cc
src/codegen/gen_delayed.cc
src/codegen/gen_dfa.cc
src/codegen/gen_goto.cc
src/codegen/gen_program.cc
src/codegen/gen_state.cc
src/codegen/helpers.cc
src/codegen/render.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/nfa/estimate_size.cc
src/options/symtab.cc
src/nfa/re_to_nfa.cc
src/adfa/adfa.cc
src/adfa/prepare.cc
src/debug/dump_adfa.cc
src/debug/dump_cfg.cc
src/debug/dump_dfa.cc
@@ -174,26 +159,21 @@ set(re2c_sources
src/dfa/fillpoints.cc
src/dfa/find_state.cc
src/dfa/minimization.cc
src/dfa/stacmd.cc
src/dfa/tagver_table.cc
src/dfa/tcmd.cc
src/encoding/ebcdic/ebcdic_regexp.cc
src/encoding/ebcdic.cc
src/encoding/enc.cc
src/encoding/range_suffix.cc
src/encoding/utf8/utf8_regexp.cc
src/encoding/utf8/utf8.cc
src/encoding/utf16/utf16_regexp.cc
src/encoding/utf16/utf16.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/rule.cc
src/regexp/regexp.cc
src/regexp/split_charset.cc
src/regexp/tag.cc
src/compile.cc
src/skeleton/control_flow.cc
src/skeleton/generate_code.cc
src/skeleton/generate_data.cc
@@ -201,13 +181,8 @@ set(re2c_sources
src/skeleton/skeleton.cc
src/parse/ast.cc
src/parse/input.cc
src/parse/normalize.cc
src/parse/scanner.cc
src/parse/unescape.cc
src/parse/validate.cc
src/util/get_dir.cc
src/util/s_to_n32_unsafe.cc
src/util/temp_file.cc
src/util/file_utils.cc
src/util/string_utils.cc
src/util/range.cc
src/main.cc
$<TARGET_OBJECTS:re2c_objects_autogen>
@@ -220,7 +195,13 @@ add_executable(re2c ${re2c_sources})
# re2go
if (RE2C_BUILD_RE2GO)
add_executable(re2go ${re2c_sources})
target_compile_definitions(re2go PUBLIC "RE2C_LANG=LANG_GO")
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")
@@ -229,117 +210,160 @@ 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)
set(re2c_docs_sources
"${re2c_manpage_source}"
"doc/manual/api/api.rst_"
"doc/manual/api/interface.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.rst_"
"doc/manual/submatch/submatch.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/conditions/parse_u32_conditions.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/src/lexer/lexer.h"
"examples/c/includes/include.re"
"examples/c/includes/definitions.h"
"examples/c/reuse/reuse.re"
"examples/c/state/push.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/conditions/parse_u32_conditions.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/src/lexer/lexer.go"
"examples/go/includes/include.re"
"examples/go/includes/definitions.go"
"examples/go/reuse/reuse.re"
"examples/go/state/push.re"
"examples/go/submatch/01_stags.re"
"examples/go/submatch/02_mtags.re"
"examples/go/submatch/03_posix.re"
)
# docs
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_help("${re2c_help_source}" "${re2c_help}" "${re2c_help_bootstrap}")
add_custom_target(docs DEPENDS "${re2c_docs}")
# install
if(UNIX)
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()
install(FILES include/unicode_categories.re DESTINATION "${RE2C_STDLIB_DIR}")
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 -E remove_directory "src"
COMMAND cmake -E remove_directory "doc"
COMMAND cmake --build "${CMAKE_CURRENT_BINARY_DIR}"
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 "${RE2C_RUN_TESTS}"
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 "${RE2C_RUN_TESTS}" --valgrind
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 "${RE2C_RUN_TESTS}" --wine -j1
COMMAND "${Python3_EXECUTABLE}" "${RE2C_RUN_TESTS}" --wine -j1
)
add_dependencies(wtests re2c)
add_executable(re2c_test_range
@@ -348,11 +372,10 @@ if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
src/test/range/test.h
src/util/range.cc
src/util/range.h
src/util/static_assert.h
)
add_executable(re2c_test_s_to_n32_unsafe
src/test/s_to_n32_unsafe/test.cc
src/util/s_to_n32_unsafe.cc
src/util/string_utils.cc
)
add_executable(re2c_test_ver_to_vernum
src/test/ver_to_vernum/test.cc
@@ -389,21 +412,26 @@ if (RE2C_BUILD_LIBS)
re2c_bootstrap_lexer("lib/lex.re" "lib/lex.cc")
re2c_bootstrap_parser("lib/parse.ypp" "lib/parse.cc" "lib/parse.h")
add_library(libre2c_objects OBJECT
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/regexec_nfa_posix_backward.cc
lib/regexec_nfa_posix_kuklewicz.cc
lib/regfree.cc
lib/stubs.cc
src/parse/ast.cc
src/parse/unescape.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
@@ -427,35 +455,28 @@ if (RE2C_BUILD_LIBS)
src/dfa/fillpoints.cc
src/dfa/find_state.cc
src/dfa/minimization.cc
src/dfa/stacmd.cc
src/dfa/tagver_table.cc
src/dfa/tcmd.cc
src/nfa/estimate_size.cc
src/nfa/re_to_nfa.cc
src/encoding/enc.cc
src/encoding/range_suffix.cc
src/encoding/ebcdic/ebcdic_regexp.cc
src/encoding/utf16/utf16.cc
src/encoding/utf16/utf16_regexp.cc
src/encoding/utf8/utf8.cc
src/encoding/utf8/utf8_regexp.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/rule.cc
src/regexp/regexp.cc
src/regexp/split_charset.cc
src/regexp/tag.cc
src/skeleton/control_flow.cc
src/skeleton/maxpath.cc
src/skeleton/skeleton.cc
src/util/range.cc
src/util/s_to_n32_unsafe.cc
)
set(libre2c_sources
$<TARGET_OBJECTS:libre2c_objects>
src/util/file_utils.cc
src/util/string_utils.cc
$<TARGET_OBJECTS:libre2c_objects_autogen>
$<TARGET_OBJECTS:re2c_objects_autogen_ver_to_vernum>
)
@@ -491,28 +512,25 @@ if (RE2C_BUILD_LIBS)
# 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
)
# libre2c benchmark
add_executable(bench_libre2c lib/bench.cc)
set_property(TARGET bench_libre2c PROPERTY CXX_STANDARD 11)
target_link_libraries(bench_libre2c libre2c)
# if have re2, add it to the benchmark
find_path(RE2_INCLUDE_DIRECTORY "re2/re2.h")
find_library(RE2_LIBRARY re2)
if (RE2_INCLUDE_DIRECTORY AND RE2_LIBRARY)
target_compile_definitions(bench_libre2c PRIVATE "HAVE_RE2_RE2_H=1")
target_include_directories(bench_libre2c PRIVATE "${RE2_INCLUDE_DIRECTORY}")
target_link_libraries(bench_libre2c "${RE2_LIBRARY}")
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)
+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.
+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.
+158 -104
View File
@@ -1,3 +1,4 @@
SUBDIRS = .
# stdlib directory
stdlibdir = $(datadir)/re2c/stdlib
@@ -9,7 +10,7 @@ if DEBUG
AM_CXXFLAGS += -DRE2C_DEBUG
endif
RE2CFLAGS = -br -W -Wno-match-empty-string
RE2CFLAGS = -b -W -Wno-match-empty-string --no-generation-date
# binary
bin_PROGRAMS = re2c
@@ -17,10 +18,12 @@ 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/adfa/action.h \
src/options/symtab.h \
src/adfa/adfa.h \
src/cfg/cfg.h \
src/dfa/closure_leftmost.h \
@@ -28,73 +31,51 @@ re2c_HDR = \
src/dfa/determinization.h \
src/dfa/dfa.h \
src/dfa/posix_precedence.h \
src/dfa/stacmd.h \
src/dfa/tag_history.h \
src/dfa/tagver_table.h \
src/dfa/tcmd.h \
src/nfa/nfa.h \
src/encoding/case.h \
src/encoding/ebcdic/ebcdic.h \
src/encoding/ebcdic/ebcdic_regexp.h \
src/encoding/ebcdic.h \
src/encoding/enc.h \
src/encoding/range_suffix.h \
src/encoding/utf8/utf8.h \
src/encoding/utf8/utf8_regexp.h \
src/encoding/utf16/utf16_regexp.h \
src/encoding/utf16/utf16.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/empty_class_policy.h \
src/regexp/re.h \
src/regexp/regexp.h \
src/regexp/rule.h \
src/regexp/tag.h \
src/compile.h \
src/skeleton/mtag_trie.h \
src/skeleton/path.h \
src/skeleton/skeleton.h \
src/parse/ast.h \
src/parse/input.h \
src/parse/parse.h \
src/parse/scanner.h \
src/parse/unescape.h \
src/debug/debug.h \
src/util/allocate.h \
src/util/allocator.h \
src/util/attribute.h \
src/util/c99_stdint.h \
src/util/fixed_allocator.h \
src/util/containers.h \
src/util/check.h \
src/util/file_utils.h \
src/util/forbid_copy.h \
src/util/free_list.h \
src/util/get_dir.h \
src/util/hash32.h \
src/util/local_increment.h \
src/util/lookup.h \
src/util/nowarn_in_bison.h \
src/util/range.h \
src/util/s_to_n32_unsafe.h \
src/util/slab_allocator.h \
src/util/smart_ptr.h \
src/util/static_assert.h \
src/util/string_utils.h \
src/util/temp_file.h \
src/util/u32lim.h \
src/util/uniq_vector.h \
src/util/wrap_iter.h
src/util/u32lim.h
re2c_SRC = \
src/codegen/code_goto.cc \
src/codegen/combine.cc \
src/codegen/gen_bitmaps.cc \
src/codegen/gen_delayed.cc \
src/codegen/gen_dfa.cc \
src/codegen/gen_goto.cc \
src/codegen/gen_program.cc \
src/codegen/gen_state.cc \
src/codegen/helpers.cc \
src/codegen/render.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/nfa/estimate_size.cc \
src/options/symtab.cc \
src/nfa/re_to_nfa.cc \
src/adfa/adfa.cc \
src/adfa/prepare.cc \
src/debug/dump_adfa.cc \
src/debug/dump_cfg.cc \
src/debug/dump_dfa.cc \
@@ -118,26 +99,21 @@ re2c_SRC = \
src/dfa/fillpoints.cc \
src/dfa/find_state.cc \
src/dfa/minimization.cc \
src/dfa/stacmd.cc \
src/dfa/tagver_table.cc \
src/dfa/tcmd.cc \
src/encoding/ebcdic/ebcdic_regexp.cc \
src/encoding/ebcdic.cc \
src/encoding/enc.cc \
src/encoding/range_suffix.cc \
src/encoding/utf8/utf8_regexp.cc \
src/encoding/utf8/utf8.cc \
src/encoding/utf16/utf16_regexp.cc \
src/encoding/utf16/utf16.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/rule.cc \
src/regexp/regexp.cc \
src/regexp/split_charset.cc \
src/regexp/tag.cc \
src/compile.cc \
src/skeleton/control_flow.cc \
src/skeleton/generate_code.cc \
src/skeleton/generate_data.cc \
@@ -145,13 +121,8 @@ re2c_SRC = \
src/skeleton/skeleton.cc \
src/parse/ast.cc \
src/parse/input.cc \
src/parse/normalize.cc \
src/parse/scanner.cc \
src/parse/unescape.cc \
src/parse/validate.cc \
src/util/get_dir.cc \
src/util/s_to_n32_unsafe.cc \
src/util/temp_file.cc \
src/util/file_utils.cc \
src/util/string_utils.cc \
src/util/range.cc
re2c_SOURCES = \
src/main.cc \
@@ -187,10 +158,12 @@ 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) \
@@ -214,8 +187,8 @@ re2c_CUSTOM = \
# docs
re2c_SRC_DOC = doc/manpage.rst
re2c_SRC_DOC_EXT = \
doc/manual/api/api.rst_ \
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_ \
@@ -240,13 +213,24 @@ re2c_SRC_DOC_EXT = \
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 \
@@ -254,16 +238,21 @@ re2c_SRC_DOC_EXT = \
examples/c/fill/01_fill.re \
examples/c/fill/02_fill.re \
examples/c/headers/header.re \
examples/c/headers/src/lexer/lexer.h \
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 \
@@ -271,32 +260,79 @@ re2c_SRC_DOC_EXT = \
examples/go/fill/01_fill.re \
examples/go/fill/02_fill.re \
examples/go/headers/header.re \
examples/go/headers/src/lexer/lexer.go \
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/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 \
@@ -312,13 +348,8 @@ if REBUILD_LEXERS
# generate lexer and update bootstrap files
.re.cc:
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)if test -x $(RE2C_FOR_BUILD); \
then \
$(RE2C_FOR_BUILD) $(RE2CFLAGS) -o $@ $< && \
cp $(@:cc=[ch]*) $(top_srcdir)/bootstrap/$(@D); \
else \
echo "RE2C is not an executable file" && exit 1 ; \
fi
$(AM_V_GEN)$(RE2C_FOR_BUILD) $(RE2CFLAGS) -o $@ $<
$(AM_V_GEN)cp $(@:cc=[ch]*) $(top_srcdir)/bootstrap/$(@D);
else
# copy bootstrap files
.re.cc:
@@ -327,19 +358,19 @@ else
$(AM_V_at)echo "Reconfigure with --enable-lexers to regenerate $@"
endif
# cannot update bootstrap with distcheck (it makes srcdir readonly),
# so we update bootstrap only on incremental build (if re2c binary exists)
if REBUILD_PARSERS
# generate lexer and update bootstrap files
.ypp.cc:
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)if test $(BISON) = "no"; \
then \
cp $(top_srcdir)/bootstrap/$(@:cc=*) $(@D); \
else \
$(BISON) --output=$@ --defines=$(@:cc=h) $< && \
if test -x $(top_builddir)/re2c$(EXEEXT); then \
cp $@ $(@:cc=h) $(top_srcdir)/bootstrap/$(@D); \
fi; \
fi
$(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)
@@ -353,29 +384,35 @@ bootstrap: all
.PHONY: docs
if REBUILD_DOCS
docs: $(DOCS) $(re2c_GEN_HELP)
GENHELP = $(top_srcdir)/build/gen_help.sh
SPLITMAN = $(top_srcdir)/build/split_man.sh
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)
$(DOC_C): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN) $(RST2MAN)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).c c \
&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).c > $@ \
$(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)
$(DOC_GO): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN) $(RST2MAN)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).go go \
&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).go > $@ \
$(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 help
$(re2c_GEN_HELP): $(re2c_CUSTOM_HELP) $(GENHELP)
# generate manpage for Rust
$(DOC_RUST): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN) $(RST2MAN)
$(AM_V_at)$(MKDIR_P) $(@D)
$(AM_V_GEN)$(RST2MAN) $(top_builddir)/$(re2c_CUSTOM_HELP) > $@.1 \
&& $(GENHELP) $@.1 $@ \
&& cp $@ $(top_srcdir)/$(re2c_BOOT_HELP) \
&& rm $@.1
$(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"
@@ -387,6 +424,10 @@ $(DOC_C): $(re2c_BOOT_DOC_C)
$(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)
@@ -396,28 +437,27 @@ endif
all-local: docs $(re2c_BOOT_PARSER)
# tests
re2c_TESTSUITE = run_tests.sh
re2c_TESTSUITE = run_tests.py
.PHONY: tests
tests: all $(re2c_TESTSUITE)
$(top_builddir)/$(re2c_TESTSUITE)
$(PYTHON) $(top_builddir)/$(re2c_TESTSUITE)
.PHONY: vtests
vtests: all $(re2c_TESTSUITE)
$(top_builddir)/$(re2c_TESTSUITE) --valgrind
$(PYTHON) $(top_builddir)/$(re2c_TESTSUITE) --valgrind
.PHONY: wtests
wtests: all $(re2c_TESTSUITE)
$(top_builddir)/$(re2c_TESTSUITE) --wine -j1
$(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 \
src/util/static_assert.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/s_to_n32_unsafe.cc
src/util/string_utils.cc
re2c_test_ver_to_vernum_SOURCES = \
src/test/ver_to_vernum/test.cc \
@@ -436,7 +476,13 @@ TESTS = \
$(re2c_TESTSUITE) \
$(check_PROGRAMS)
# libraries go here (in included .am files)
# 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 =
@@ -446,7 +492,15 @@ endif
# re2go
if WITH_GOLANG
bin_PROGRAMS += re2go
re2go_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=LANG_GO
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
+42 -48
View File
@@ -7,11 +7,14 @@ 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/adfa/action.h \
src/options/symtab.h \
src/adfa/adfa.h \
src/cfg/cfg.h \
src/dfa/closure_leftmost.h \
@@ -19,72 +22,55 @@ libre2c_la_HDR = \
src/dfa/determinization.h \
src/dfa/dfa.h \
src/dfa/posix_precedence.h \
src/dfa/stacmd.h \
src/dfa/tag_history.h \
src/dfa/tagver_table.h \
src/dfa/tcmd.h \
src/nfa/nfa.h \
src/encoding/case.h \
src/encoding/ebcdic/ebcdic.h \
src/encoding/ebcdic/ebcdic_regexp.h \
src/encoding/ebcdic.h \
src/encoding/enc.h \
src/encoding/range_suffix.h \
src/encoding/utf8/utf8.h \
src/encoding/utf8/utf8_regexp.h \
src/encoding/utf16/utf16_regexp.h \
src/encoding/utf16/utf16.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/empty_class_policy.h \
src/regexp/re.h \
src/regexp/regexp.h \
src/regexp/rule.h \
src/regexp/tag.h \
src/compile.h \
src/skeleton/path.h \
src/skeleton/skeleton.h \
src/parse/ast.h \
src/parse/unescape.h \
src/parse/input.h \
src/parse/parser.h \
src/parse/scanner.h \
src/parse/unescape.h \
src/debug/debug.h \
src/util/allocate.h \
src/util/allocator.h \
src/util/attribute.h \
src/util/c99_stdint.h \
src/util/check.h \
src/util/containers.h \
src/util/file_utils.h \
src/util/forbid_copy.h \
src/util/free_list.h \
src/util/get_dir.h \
src/util/hash32.h \
src/util/local_increment.h \
src/util/lookup.h \
src/util/nowarn_in_bison.h \
src/util/range.h \
src/util/s_to_n32_unsafe.h \
src/util/slab_allocator.h \
src/util/smart_ptr.h \
src/util/static_assert.h \
src/util/string_utils.h \
src/util/u32lim.h \
src/util/uniq_vector.h \
src/util/wrap_iter.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/regexec_nfa_posix_backward.cc \
lib/regexec_nfa_posix_kuklewicz.cc \
lib/regfree.cc \
lib/stubs.cc \
src/parse/ast.cc \
src/parse/unescape.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 \
@@ -108,32 +94,28 @@ libre2c_la_SRC = \
src/dfa/fillpoints.cc \
src/dfa/find_state.cc \
src/dfa/minimization.cc \
src/dfa/stacmd.cc \
src/dfa/tagver_table.cc \
src/dfa/tcmd.cc \
src/nfa/estimate_size.cc \
src/nfa/re_to_nfa.cc \
src/encoding/enc.cc \
src/encoding/range_suffix.cc \
src/encoding/ebcdic/ebcdic_regexp.cc \
src/encoding/utf16/utf16.cc \
src/encoding/utf16/utf16_regexp.cc \
src/encoding/utf8/utf8.cc \
src/encoding/utf8/utf8_regexp.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/rule.cc \
src/regexp/regexp.cc \
src/regexp/split_charset.cc \
src/regexp/tag.cc \
src/skeleton/control_flow.cc \
src/skeleton/maxpath.cc \
src/skeleton/skeleton.cc \
src/util/range.cc \
src/util/s_to_n32_unsafe.cc
src/util/file_utils.cc \
src/util/string_utils.cc
libre2c_la_SOURCES = \
$(libre2c_la_HDR) \
@@ -142,11 +124,13 @@ libre2c_la_SOURCES = \
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
@@ -161,6 +145,7 @@ 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)
@@ -174,13 +159,22 @@ CLEANFILES += $(libre2c_la_GEN)
# lexer depends on bison-generated header
lib/lex.cc: lib/parse.cc
test_libre2c_SOURCES = lib/test.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
bench_libre2c_SOURCES = lib/bench.cc
bench_libre2c_CXXFLAGS = $(AM_CXXFLAGS) -std=c++11
bench_libre2c_LDFLAGS = $(LDFLAGS_RE2)
bench_libre2c_LDADD = libre2c.la
noinst_PROGRAMS += bench_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
+15 -7
View File
@@ -1,7 +1,7 @@
DESCRIPTION
-----------
re2c is a free and open-source lexer generator for C, C++ and Go.
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
@@ -36,12 +36,18 @@ $ 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
-----
re2c has two build systems: Autotools and CMake. Both are maintained and tested
on Travis CI. See [the documentation](http://re2c.org/install/install.html) for
See BUILD.md or the [online docs](https://re2c.org/build/build.html) for
instructions how to build re2c.
@@ -57,15 +63,17 @@ Mailing lists:
- re2c-general@lists.sourceforge.net
- re2c-devel@lists.sourceforge.net
IRC channel:
IRC channels:
- freenode/#re2c
- 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 people contributed to the project. The current maintainer is
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()
-2
View File
@@ -1,5 +1,3 @@
#!/bin/sh
git clean -fX
mkdir -p m4
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
-47
View File
@@ -1,47 +0,0 @@
To run benchmarks:
1. Create symlink to the RE2C binary (version 1.0 or older) in the current
directory.
2. Generate input data: files ./http/gen/http.dat and ./uri/gen/uri.dat.
Random data can be generated with the following programs (written in
haskell):
http/gen/gen_http.hs
uri/gen/gen_uri.hs
Use the following scripts to build generators:
http/gen/mk_gen.sh
uri/gen/mk_gen.sh
The size of the generated data is hard-coded in the source code of
generators (and can be easily tweaked).
Alternatively, if you don't have haskell compiler or for any other reason
are unable to build generators, use small data samples provided for each
benchmark (one can copy-paste them many times with 'cat' to obtain a large
input file):
http/gen/sample.dat
uri/gen/sample.dat
3.Run scripts:
./http/simple/__bench.sh
./http/simple/__bench_b.sh
./http/simple/__bench_unopt.sh
./http/rfc7230/__bench.sh
./http/rfc7230/__bench_b.sh
./http/rfc7230/__bench_unopt.sh
./uri/simple/__bench.sh
./uri/simple/__bench_b.sh
./uri/simple/__bench_unopt.sh
./uri/rfc3986/__bench.sh
./uri/rfc3986/__bench_b.sh
./uri/rfc3986/__bench_unopt.sh
Alternatively, run ./__run.sh (it will drop logs in each subdirectory).
-116
View File
@@ -1,116 +0,0 @@
re2c="../../re2c"
compile() {
name="${1}_${2}"
opts="$3"
[ -e ${re2c} ] || { echo "*** no re2c ***"; exit 1; }
${re2c} ${opts} -W ${name}.re -o ${name}_lookahead.c && ls -l --block-size=K ${name}_lookahead.c
${re2c} ${opts} --no-lookahead -W ${name}.re -o ${name}_no_lookahead.c && ls -l --block-size=K ${name}_no_lookahead.c
${re2c} ${opts} -W ${name}_notags.re -o ${name}_notags.c && ls -l --block-size=K ${name}_notags.c
}
run() {
name1="$1"
name2="$2"
name="${name1}_${name2}"
input="../gen/${name1}.dat"
[ -e ${input} ] || { echo "*** no input file ***"; exit 1; }
strip ${name}
cmd="./${name} ${input}"
for i in `seq 1`; do $cmd >/dev/null 2>&1; done # warmup
npass=4
total=0
for i in `seq $npass`; do
t="`TIMEFORMAT='%E'; time ( $cmd 2>/dev/null ) 2>&1 1>/dev/null`"
echo "t:" $t
total=`echo $total + $t | bc -l`
done
average=`echo "$total / $npass" | bc -l`
echo "time: $average"
ls -l --block-size=K ${name}
}
#cflags="-Wall -O2"
cflags="-O2"
run_all() {
name1="$1"
name2="$2"
name="${name1}_${name2}"
echo "---------------- WARMUP (GCC -O2 lookahead) ----------------"
gcc $cflags ${name}_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- END WARMUP ----------------"
echo "---------------- GCC -O2 lookahead ----------------"
gcc $cflags ${name}_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- GCC -O2 no-lookahead ----------------"
gcc $cflags ${name}_no_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- GCC -O2 notags ----------------"
gcc $cflags ${name}_notags.c -o${name} && run ${name1} ${name2}
echo "---------------- CLANG -O2 lookahead ----------------"
clang $cflags ${name}_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- CLANG -O2 no-lookahead ----------------"
clang $cflags ${name}_no_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- CLANG -O2 notags ----------------"
clang $cflags ${name}_notags.c -o${name} && run ${name1} ${name2}
echo "---------------- TCC -O2 lookahead ----------------"
tcc $cflags ${name}_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- TCC -O2 no-lookahead ----------------"
tcc $cflags ${name}_no_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- TCC -O2 notags ----------------"
tcc $cflags ${name}_notags.c -o${name} && run ${name1} ${name2}
echo "---------------- PCC -O2 lookahead ----------------"
pcc $cflags ${name}_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- PCC -O2 no-lookahead ----------------"
pcc $cflags ${name}_no_lookahead.c -o${name} && run ${name1} ${name2}
echo "---------------- PCC -O2 notags ----------------"
pcc $cflags ${name}_notags.c -o${name} && run ${name1} ${name2}
# echo "---------------- NWCC -O2 lookahead ----------------"
# nwcc $cflags ${name}_lookahead.c -o${name} && run ${name1} ${name2}
# echo "---------------- NWCC -O2 no-lookahead ----------------"
# nwcc $cflags ${name}_no_lookahead.c -o${name} && run ${name1} ${name2}
# echo "---------------- NWCC -O2 notags ----------------"
# nwcc $cflags ${name}_notags.c -o${name} && run ${name1} ${name2}
rm ${name}_lookahead.c
rm ${name}_no_lookahead.c
rm ${name}_notags.c
rm ${name}
}
verify() {
name1="$1"
name2="$2"
name=${name1}_${name2}
input="../gen/${name1}.dat.short"
output="${name1}.dat.short"
[ -e ${input} ] || { echo "*** no input file ***"; exit 1; }
[ -e ${re2c} ] || { echo "*** no re2c ***"; exit 1; }
${re2c} -W ${name}.re -o ${name}_lookahead.c
${re2c} --no-lookahead -W ${name}.re -o ${name}_no_lookahead.c
${re2c} -W ${name}_notags.re -o ${name}_notags.c
g++ -Wall -O2 -DVERIFY ${name}_lookahead.c -o${name} && ./${name} ${input} > ${output} && diff -q ${input} ${output} || echo "lookahead failed"
g++ -Wall -O2 -DVERIFY ${name}_no_lookahead.c -o${name} && ./${name} ${input} > ${output} && diff -q ${input} ${output} || echo "non-lookahead failed"
g++ -Wall -O2 -DVERIFY ${name}_notags.c -o${name} && ./${name} ${input} > ${output} && diff -q ${input} ${output} || echo "notags failed"
rm ${name}_lookahead.c
rm ${name}_no_lookahead.c
rm ${name}_notags.c
rm ${name}
rm ${output}
}
-21
View File
@@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -e
bench() {
cd "$1/$2/"
# ./__verify.sh
./__bench.sh 1> log._ 2>&1
./__bench_unopt.sh 1> log.unopt 2>&1
./__bench_b.sh 1> log.b 2>&1
cd ../..
}
bench http rfc7230
bench http simple
bench uri rfc3986
bench uri simple
+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_
-365
View File
@@ -1,365 +0,0 @@
import qualified Test.QuickCheck as Q
import Data.List (intercalate)
import Control.Monad (forM_, when, replicateM)
{-!re2c
crlf = "\n";
sp = " ";
htab = "\t";
ows = (sp | htab)*;
rws = (sp | htab)+;
bws = ows;
digit = [0-9];
alpha = [a-zA-Z];
hexdigit = [0-9a-fA-F];
unreserved = alpha | digit | [-._~];
pct_encoded = "%" hexdigit{2};
sub_delims = [!$&'()*+,;=];
pchar = unreserved | pct_encoded | sub_delims | [:@];
vchar = [\x1f-\x7e];
tchar = [-!#$%&'*+.^_`|~] | digit | alpha;
token = tchar+;
octet = [^\x00];
obs_fold = crlf (sp | htab)+;
obs_text = [\x80-\xff];
field_name = token;
field_vchar = vchar | obs_text;
field_content = field_vchar ((sp | htab)+ field_vchar)?;
field_value = (field_content | obs_fold)*;
header_field = #h1 field_name #h2 ":" ows field_value ows #h3;
method = token;
segment = pchar*;
scheme = alpha (alpha | digit | [-+.])*;
userinfo = (unreserved | pct_encoded | sub_delims | ":")*;
dec_octet
= digit
| [\x31-\x39] digit
| "1" digit{2}
| "2" [\x30-\x34] digit
| "25" [\x30-\x35];
ipv4address = dec_octet "." dec_octet "." dec_octet "." dec_octet;
h16 = hexdigit{1,4};
ls32 = h16 ":" h16 | ipv4address;
ipv6address
= (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)? "::";
ipvfuture = "v" hexdigit+ "." (unreserved | sub_delims | ":" )+;
ip_literal = "[" ( ipv6address | ipvfuture ) "]";
reg_name = (unreserved | pct_encoded | sub_delims)*;
host = ip_literal | ipv4address | reg_name;
port = digit*;
authority = (userinfo "@")? host (":" port)?;
query = (pchar | [/?])*;
path_abempty = ("/" pchar*)*;
path_absolute = "/" (pchar+ ("/" pchar*)*)?;
path_rootless = pchar+ ("/" pchar*)*;
path_empty = "";
hier_part
= "//" authority path_abempty
| (path_absolute | path_rootless | path_empty);
absolute_uri = scheme ":" hier_part ("?" query)?;
absolute_path = ("/" segment)*;
origin_form = absolute_path ("?" query)?;
http_name = "HTTP";
http_version = http_name "/" digit "." digit;
request_target = origin_form | absolute_uri | authority | "*";
request_line = @m1 method @m2 sp @rt1 request_target @rt2 sp @v3 http_version @v4 crlf;
status_code = digit{3};
reason_phrase = (htab | sp | vchar | obs_text)*;
status_line = @v1 http_version @v2 sp @s1 status_code @s2 sp @rp1 reason_phrase @rp2 crlf;
start_line = (request_line | status_line);
message_body = octet*;
message_head = start_line (header_field crlf)* crlf;
-}
type Scheme = String
type User = String
type Password = String
type Host = String
type Port = String
type Path = String
type Query = String
data RequestTarget
= OriginForm Path Query
| AbsoluteURI Scheme User Password Host Port Path Query
| Authority User Password Host Port
| Asterisk
type ReasonPhrase = String
type HTTPVersion = String
type Method = String
type StatusCode = Int
data StartLine
= RequestLine Method RequestTarget HTTPVersion
| StatusLine HTTPVersion StatusCode ReasonPhrase
data HeaderField = HeaderField String
data HTTPMsg = HTTPMsg StartLine [HeaderField]
instance Show RequestTarget where
show (OriginForm p q) = p ++ (if q == "" then "" else "?" ++ q)
show (AbsoluteURI sc us pw ho pr pa q) = concat
[ sc
, ":"
, if ho == "" then "" else "//"
, us
, if us == "" then "" else ":"
, pw
, if pw == "" then "" else "@"
, ho
, if pr == "" then "" else ":"
, pr
, pa
, if q == "" then "" else "?"
, q
]
show (Authority us pw ho pr) = concat
[ us
, if us == "" then "" else ":"
, pw
, if pw == "" then "" else "@"
, ho
, if pr == "" then "" else ":"
, pr
]
show Asterisk = "*"
instance Show StartLine where
show (RequestLine m rt v) = m ++ " " ++ show rt ++ " " ++ v ++ "\n"
show (StatusLine v sc rp) = v ++ " " ++ show sc ++ " " ++ rp ++ "\n"
instance Show HeaderField where show (HeaderField hf) = hf
instance Show HTTPMsg where
show (HTTPMsg sl hfs) = show sl ++ unlines (map show hfs) ++ "\n"
instance Q.Arbitrary HTTPMsg where
arbitrary = do
scheme <- Q.elements ["http", "https", "ftp", "file"]
user <- lstr
password <- anstr
host <- Q.frequency [(10, ipv4), (10, hostname), (1, ipv6)]
port <- mayb $ show <$> (Q.choose (0, 10000) :: Q.Gen Int)
path <- filepath
query <- mayb anstr
request_target <- Q.frequency
[ (1, pure $ OriginForm path query)
, (1, pure $ OriginForm path "")
, (1, pure $ Authority user password host port)
, (1, pure $ Authority user password host "")
, (1, pure $ Authority "" "" host port)
, (1, pure $ Authority "" "" host "")
, (1, pure $ AbsoluteURI scheme user password host port path query)
, (2, pure $ AbsoluteURI scheme "" "" host port path query)
, (1, pure $ AbsoluteURI scheme "" "" "" "" path query)
, (1, pure Asterisk)
]
reason_phrase <- Q.listOf (Q.elements (alphanum ++ space)) :: Q.Gen [Char]
method <- Q.elements
[ "OPTIONS"
, "GET"
, "HEAD"
, "POST"
, "PUT"
, "DELETE"
, "TRACE"
, "CONNECT"
, "PATCH"
]
status_code <- Q.choose (100, 999) :: Q.Gen Int
http_version <- do
n1 <- Q.choose (0, 9) :: Q.Gen Int
n2 <- Q.choose (0, 9) :: Q.Gen Int
return $ "HTTP/" ++ show n1 ++ "." ++ show n2
start_line <- Q.frequency
[ (1, pure $ RequestLine method request_target http_version)
, (1, pure $ StatusLine http_version status_code reason_phrase)
]
-- copy-pasted from https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
header_fields <- Q.listOf1 $ HeaderField <$> Q.elements
-- request examples
[ "Accept: text/plain"
, "Accept-Charset: utf-8"
, "Accept-Encoding: gzip, deflate"
, "Accept-Language: en-US"
, "Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT"
, "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
, "Cache-Control: no-cache"
, "Connection: keep-alive"
, "Connection: Upgrade"
, "Cookie: $Version=1; Skin=new;"
, "Content-Length: 348"
, "Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ=="
, "Content-Type: application/x-www-form-urlencoded"
, "Date: Tue, 15 Nov 1994 08:12:31 GMT"
, "Expect: 100-continue"
, "Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43"
, "Forwarded: for=192.0.2.43, for=198.51.100.17"
, "From: user@example.com"
, "Host: en.wikipedia.org:8080"
, "Host: en.wikipedia.org"
, "If-Match: \"737060cd8c284d8af7ad3082f209582d\""
, "If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT"
, "If-None-Match: \"737060cd8c284d8af7ad3082f209582d\""
, "If-Range: \"737060cd8c284d8af7ad3082f209582d\""
, "If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT"
, "Max-Forwards: 10"
, "Origin: http://www.example-social-network.com"
, "Pragma: no-cache"
, "Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
, "Range: bytes=500-999"
, "Referer: http://en.wikipedia.org/wiki/Main_Page"
, "TE: trailers, deflate"
, "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0"
, "Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket"
, "Via: 1.0 fred, 1.1 example.com (Apache/1.1)"
, "Warning: 199 Miscellaneous warning"
, "X-Requested-With: XMLHttpRequest"
, "DNT: 1 (Do Not Track Enabled)"
, "DNT: 0 (Do Not Track Disabled)"
, "X-Forwarded-For: client1, proxy1, proxy2"
, "X-Forwarded-For: 129.78.138.66, 129.78.64.103"
, "X-Forwarded-Host: en.wikipedia.org:8080"
, "X-Forwarded-Host: en.wikipedia.org"
, "X-Forwarded-Proto: https"
, "Front-End-Https: on"
, "X-HTTP-Method-Override: DELETE"
, "X-Att-Deviceid: GT-P7320/P7320XXLPG"
, "x-wap-profile: http://wap.samsungmobile.com/uaprof/SGH-I777.xml"
, "Proxy-Connection: keep-alive"
, "X-UIDH: ..."
, "X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql"
, "X-Request-ID: f058ebd6-02f7-4d3f-942e-904344e8cde5"
-- response examples
, "Access-Control-Allow-Origin: *"
, "Accept-Patch: text/example;charset=utf-8"
, "Accept-Ranges: bytes"
, "Age: 12"
, "Allow: GET, HEAD"
, "Alt-Svc: http/1.1=\"http2.example.com:8001\"; ma=7200"
, "Cache-Control: max-age=3600"
, "Connection: close"
, "Content-Disposition: attachment; filename=\"fname.ext\""
, "Content-Encoding: gzip"
, "Content-Language: da"
, "Content-Length: 51"
, "Content-Location: /index.htm"
, "Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ=="
, "Content-Range: bytes 21010-47021/47022"
, "Content-Type: text/html; charset=utf-8"
, "Date: Tue, 15 Nov 1994 08:12:31 GMT"
, "ETag: \"737060cd8c284d8af7ad3082f209582d\""
, "Expires: Thu, 01 Dec 1994 16:00:00 GMT"
, "Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT"
, "Link: </feed>; rel=\"alternate\""
, "Location: http://www.w3.org/pub/WWW/People.html"
, "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.\""
, "Pragma: no-cache"
, "Proxy-Authenticate: Basic"
, "Public-Key-Pins: max-age=2592000; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\";"
, "Refresh: 5; url=http://www.w3.org/pub/WWW/People.html"
, "Retry-After: 120"
, "Retry-After: Fri, 07 Nov 2014 23:59:59 GMT"
, "Server: Apache/2.4.1 (Unix)"
, "Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1"
, "Strict-Transport-Security: max-age=16070400; includeSubDomains"
, "Trailer: Max-Forwards"
, "Transfer-Encoding: chunked"
, "Tk: ?"
, "Upgrade: HTTPS/1.3, IRC/6.9, RTA/x11, websocket"
, "Vary: *"
, "Vary: Accept-Language"
, "Via: 1.0 fred, 1.1 example.com (Apache/1.1)"
, "Warning: 199 Miscellaneous warning"
, "WWW-Authenticate: Basic"
, "X-Frame-Options: deny"
, "Status: 200 OK"
, "X-XSS-Protection: 1; mode=block"
, "X-WebKit-CSP: default-src 'self'"
, "X-Content-Type-Options: nosniff"
, "X-Powered-By: PHP/5.4.0"
, "X-UA-Compatible: IE=EmulateIE7"
, "X-UA-Compatible: IE=edge"
, "X-UA-Compatible: Chrome=1"
, "X-Content-Duration: 42.666"
, "Upgrade-Insecure-Requests: 1"
, "X-Request-ID: f058ebd6-02f7-4d3f-942e-904344e8cde5"
]
return $ HTTPMsg start_line header_fields
lalpha :: [Char]
lalpha = ['a'..'z']
ualpha :: [Char]
ualpha = ['A'..'Z']
alpha :: [Char]
alpha = lalpha ++ ualpha
digit :: [Char]
digit = ['0'..'9']
hexdigit :: [Char]
hexdigit = ['a'..'f'] ++ ['A'..'F'] ++ digit
alphanum :: [Char]
alphanum = alpha ++ digit
space :: [Char]
space = [' ', '\t']
lstr :: Q.Gen String
lstr = Q.listOf1 (Q.elements lalpha) :: Q.Gen [Char]
anstr :: Q.Gen String
anstr = Q.listOf1 (Q.elements alphanum) :: Q.Gen [Char]
ipv4 :: Q.Gen String
ipv4 = do
let octet = show <$> (Q.choose (0,255) :: Q.Gen Int)
intercalate "." <$> replicateM 4 octet
ipv6 :: Q.Gen String
ipv6 = do
let hexgroup = do
k <- Q.choose (1, 4) :: Q.Gen Int
replicateM k (Q.elements hexdigit)
n <- Q.choose (0, 8) :: Q.Gen Int
m <- Q.choose (1, n) :: Q.Gen Int
hh <- replicateM n hexgroup
return $ (++ "]") . ("[" ++) $ case n of
8 -> intercalate ":" hh
_ -> concat [intercalate ":" (take m hh), "::", intercalate ":" (drop m hh)]
hostname :: Q.Gen String
hostname = do
subdomains <- Q.listOf1 (take 10 <$> lstr)
return $ intercalate "." $ take 5 subdomains
filepath :: Q.Gen String
filepath = do
subdirs <- Q.listOf1 lstr
return $ concat $ map ("/" ++) $ take 10 subdirs
mayb :: Q.Gen String -> Q.Gen String
mayb gen = Q.oneof [gen, pure ""]
main :: IO ()
main = do
let f = "http.dat"
writeFile f ""
forM_ [0 .. 170000 :: Int] $ \i -> do
when (i `mod` 1000 == 0) $ print i
msg <- Q.generate (Q.arbitrary :: Q.Gen HTTPMsg)
appendFile f $ show msg
-1
View File
@@ -1 +0,0 @@
ghc -O2 -Wall gen_http.hs
-6
View File
@@ -1,6 +0,0 @@
. ../../__bench_utils.sh
compile http rfc7230 ""
run_all http rfc7230
-6
View File
@@ -1,6 +0,0 @@
. ../../__bench_utils.sh
compile http rfc7230 "-b"
run_all http rfc7230
-6
View File
@@ -1,6 +0,0 @@
. ../../__bench_utils.sh
compile http rfc7230 "--no-optimize-tags"
run_all http rfc7230
-4
View File
@@ -1,4 +0,0 @@
. ../../__bench_utils.sh
verify http rfc7230
-318
View File
@@ -1,318 +0,0 @@
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct taglist_t {
struct taglist_t *pred;
long dist;
} taglist_t;
typedef struct taglistpool_t {
taglist_t *head;
taglist_t *next;
taglist_t *last;
} taglistpool_t;
typedef struct {
FILE *file;
char *buf;
char *lim;
char *cur;
char *mar;
char *tok;
/*!stags:re2c format = "char *@@;\n"; */
/*!mtags:re2c format = "taglist_t *@@;\n"; */
taglistpool_t tlp;
int eof;
} input_t;
static void taglistpool_clear(taglistpool_t *tlp, input_t *in)
{
tlp->next = tlp->head;
/*!mtags:re2c format = "in->@@ = 0;\n"; */
}
static void taglistpool_init(taglistpool_t *tlp)
{
static const unsigned size = 1024 * 1024;
tlp->head = (taglist_t*)malloc(size * sizeof(taglist_t));
tlp->next = tlp->head;
tlp->last = tlp->head + size;
}
static void taglistpool_free(taglistpool_t *tlp)
{
free(tlp->head);
tlp->head = tlp->next = tlp->last = NULL;
}
static taglist_t *taglistpool_next(taglistpool_t *tlp)
{
if (tlp->next < tlp->last) {
return tlp->next++;
}
const unsigned size = tlp->last - tlp->head;
taglist_t *head = (taglist_t*)malloc(2 * size * sizeof(taglist_t));
memcpy(head, tlp->head, size * sizeof(taglist_t));
free(tlp->head);
tlp->head = head;
tlp->next = head + size;
tlp->last = head + size * 2;
return tlp->next++;
}
static void taglist(taglist_t **ptl, const char *b, const char *t, taglistpool_t *tlp)
{
taglist_t *tl = taglistpool_next(tlp);
tl->pred = *ptl;
tl->dist = t - b;
*ptl = tl;
}
/*!max:re2c*/
static const size_t SIZE = 4096;
static void init_input(input_t *in, const char *fname)
{
in->file = fopen(fname, "r");
in->buf = (char*) malloc(SIZE + YYMAXFILL);
in->lim = in->buf + SIZE;
in->cur = in->lim;
in->mar = in->lim;
in->tok = in->lim;
/*!stags:re2c format = "in->@@ = 0;\n"; */
/*!mtags:re2c format = "in->@@ = 0;\n"; */
taglistpool_init(&in->tlp);
in->eof = 0;
}
static void free_input(input_t *in)
{
fclose(in->file);
free(in->buf);
taglistpool_free(&in->tlp);
}
static int fill(input_t *in, size_t need)
{
size_t free;
if (in->eof) return 1;
free = in->tok - in->buf;
if (free < need) return 2;
memmove(in->buf, in->tok, in->lim - in->tok);
in->lim -= free;
in->cur -= free;
in->mar -= free;
in->tok -= free;
/*!stags:re2c format = "if (in->@@) in->@@ -= free;\n"; */
in->lim += fread(in->lim, 1, free, in->file);
if (in->lim < in->buf + SIZE) {
in->eof = 1;
memset(in->lim, 0, YYMAXFILL);
in->lim += YYMAXFILL;
}
return 0;
}
static void print_headers(const char *tok,
const taglist_t *h1, const taglist_t *h2,
const taglist_t *h3, const taglist_t *h4,
const taglist_t *h5)
{
if (!h1 || !h2 || !h3 || !h4 || !h5) {
assert(!h1 && !h2 && !h3 && !h4 && !h5);
return;
}
print_headers(tok, h1->pred, h2->pred, h3->pred, h4->pred, h5->pred);
printf("%.*s%.*s%.*s%.*s\n",
(int)(h2->dist - h1->dist), tok + h1->dist,
(int)(h3->dist - h2->dist), tok + h2->dist,
(int)(h4->dist - h3->dist), tok + h3->dist,
(int)(h5->dist - h4->dist), tok + h4->dist);
}
#define YYCTYPE char
#define YYCURSOR in->cur
#define YYMARKER in->mar
#define YYLIMIT in->lim
#define YYMTAGP(tl) taglist(&tl, in->tok, in->cur, &in->tlp)
#define YYMTAGN(tl) taglist(&tl, in->tok, NULL, &in->tlp)
#define YYFILL(n) if (fill(in, n) != 0) return 2;
static int lex(input_t *in, long *count, long *total)
{
const char *of, *au, *at,
*hs1, *hs3, *m1, *p1, *p3, *p5, *q1, *q3,
*hs2, *hs4, *m2, *p2, *p4, *p6, *q2, *q4,
*r1, *r3, *rp1, *s1, *st1, *u1, *u3, *v1, *v3,
*r2, *r4, *rp2, *s2, *st2, *u2, *u4, *v2, *v4;
taglist_t *h1, *h2, *h3, *h4, *h5;
long c, t;
c = 0; t = 0;
of = au = at
= hs1 = hs3 = m1 = p1 = p3 = p5 = q1 = q3
= hs2 = hs4 = m2 = p2 = p4 = p6 = q2 = q4
= r1 = r3 = rp1 = s1 = st1 = u1 = u3 = v1 = v3
= r2 = r4 = rp2 = s2 = st2 = u2 = u4 = v2 = v4 = NULL;
loop:
in->tok = in->cur;
/*!re2c
re2c:flags:tags = 1;
re2c:tags:expression = "in->@@";
end = "\x00";
eol = "\n";
crlf = eol;
sp = " ";
htab = "\t";
ows = (sp | htab)*;
digit = [0-9];
alpha = [a-zA-Z];
hexdigit = [0-9a-fA-F];
unreserved = alpha | digit | [-._~];
pct_encoded = "%" hexdigit{2};
sub_delims = [!$&'()*+,;=];
pchar = unreserved | pct_encoded | sub_delims | [:@];
vchar = [\x1f-\x7e];
tchar = [-!#$%&'*+.^_`|~] | digit | alpha;
obs_fold = crlf (sp | htab)+;
obs_text = [\x80-\xff];
field_name = tchar+;
field_vchar = vchar | obs_text;
field_content = field_vchar ((sp | htab)+ field_vchar)?;
field_value = (field_content | obs_fold)*;
header_field = #h1 field_name #h2 ":" ows #h3 field_value #h4 ows #h5;
scheme = alpha (alpha | digit | [-+.])*;
userinfo = (unreserved | pct_encoded | sub_delims | ":")*;
dec_octet
= digit
| [\x31-\x39] digit
| "1" digit{2}
| "2" [\x30-\x34] digit
| "25" [\x30-\x35];
ipv4address = dec_octet "." dec_octet "." dec_octet "." dec_octet;
h16 = hexdigit{1,4};
ls32 = h16 ":" h16 | ipv4address;
ipv6address
= (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)? "::";
ipvfuture = "v" hexdigit+ "." (unreserved | sub_delims | ":" )+;
ip_literal = "[" ( ipv6address | ipvfuture ) "]";
reg_name = (unreserved | pct_encoded | sub_delims)*;
path_abempty = ("/" pchar*)*;
path_absolute = "/" (pchar+ ("/" pchar*)*)?;
path_rootless = pchar+ ("/" pchar*)*;
path_empty = "";
host = ip_literal | ipv4address | reg_name;
port = digit*;
query = (pchar | [/?])*;
absolute_uri = @s1 scheme @s2 ":"
( "//" (@u1 userinfo @u2 "@")? @hs1 host @hs2 (":" @r1 port @r2)? @p1 path_abempty @p2
| @p3 (path_absolute | path_rootless | path_empty) @p4
) ("?" @q1 query @q2)?;
authority = (@u3 userinfo @u4 "@")? @hs3 host @hs4 (":" @r3 port @r4)?;
origin_form = @p5 path_abempty @p6 ("?" @q3 query @q4)?;
http_name = "HTTP";
http_version = http_name "/" digit "." digit;
request_target
= @at authority
| @au absolute_uri
| @of origin_form
| "*";
method = tchar+;
request_line = @m1 method @m2 sp request_target sp @v3 http_version @v4 crlf;
status_code = digit{3};
reason_phrase = (htab | sp | vchar | obs_text)*;
status_line = @v1 http_version @v2 sp @st1 status_code @st2 sp @rp1 reason_phrase @rp2 crlf;
start_line = (request_line | status_line);
message_head = start_line (header_field crlf)* crlf;
* { return 1; }
end { *count = c; *total = t; return 0; }
eol { goto loop; }
message_head {
#ifndef VERIFY
c += 1;
if (st1) t += (v2 - v1) + (st2 - st1) + (rp2 - rp1);
if (m1) {
if (of) t += (p6 - p5) + (q4 - q3);
if (au) t += (s2 - s1) + (u2 - u1) + (hs2 - hs1)
+ (r2 - r1) + (p2 - p1) + (p4 - p3) + (q2 - q1);
if (at) t += (u4 - u3) + (hs4 - hs3) + (r4 - r3);
t += (v4 - v3);
}
for (; h1 != 0; h1 = h1->pred, h2 = h2->pred,
h3 = h3->pred, h4 = h4->pred, h5 = h5->pred) {
t += (h2->dist - h1->dist) + (h3->dist - h2->dist)
+ (h4->dist - h3->dist) + (h5->dist - h4->dist);
}
#else
if (st1) {
printf("%.*s %.*s %.*s\n",
(int)(v2 - v1), v1,
(int)(st2 - st1), st1,
(int)(rp2 - rp1), rp1);
} else if (m1) {
printf("%.*s ", (int)(m2 - m1), m1);
if (of) {
printf("%.*s", (int)(p6 - p5), p5);
if (q3) printf("?%.*s", (int)(q4 - q3), q3);
} else if (au) {
printf("%.*s:", (int)(s2 - s1), s1);
if (p1) printf("//");
if (u1) printf("%.*s@", (int)(u2 - u1), u1);
printf("%.*s", (int)(hs2 - hs1), hs1);
if (r1) printf(":%.*s", (int)(r2 - r1), r1);
if (p1) printf("%.*s", (int)(p2 - p1), p1);
if (p3) printf("%.*s", (int)(p4 - p3), p3);
if (q1) printf("?%.*s", (int)(q2 - q1), q1);
} else if (at) {
if (u3) printf("%.*s@", (int)(u4 - u3), u3);
printf("%.*s", (int)(hs4 - hs3), hs3);
if (r3) printf(":%.*s", (int)(r4 - r3), r3);
} else {
printf("*");
}
printf(" %.*s\n", (int)(v4 - v3), v3);
}
print_headers(in->tok, h1, h2, h3, h4, h5);
printf("\n");
#endif
taglistpool_clear(&in->tlp, in);
goto loop;
}
*/
}
int main(int argc, char **argv)
{
long count, total;
input_t in;
init_input(&in, argv[1]);
switch (lex(&in, &count, &total)) {
case 0: fprintf(stderr, "ok, parsed %ld HTTPs, peeked %ld chars\n", count, total); break;
case 1: fprintf(stderr, "syntax error: %s\n", in.cur); break;
case 2: fprintf(stderr, "fill failed\n"); break;
default: fprintf(stderr, "panic!\n"); break;
}
free_input(&in);
return 0;
}
@@ -1,180 +0,0 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
FILE *file;
char *buf;
char *lim;
char *cur;
char *mar;
char *tok;
int eof;
} input_t;
/*!max:re2c*/
static const size_t SIZE = 4096;
static void init_input(input_t *in, const char *fname)
{
in->file = fopen(fname, "r");
in->buf = (char*) malloc(SIZE + YYMAXFILL);
in->lim = in->buf + SIZE;
in->cur = in->lim;
in->mar = in->lim;
in->tok = in->lim;
in->eof = 0;
}
static void free_input(input_t *in)
{
fclose(in->file);
free(in->buf);
}
static int fill(input_t *in, size_t need)
{
size_t free;
if (in->eof) return 1;
free = in->tok - in->buf;
if (free < need) return 2;
memmove(in->buf, in->tok, in->lim - in->tok);
in->lim -= free;
in->cur -= free;
in->mar -= free;
in->tok -= free;
in->lim += fread(in->lim, 1, free, in->file);
if (in->lim < in->buf + SIZE) {
in->eof = 1;
memset(in->lim, 0, YYMAXFILL);
in->lim += YYMAXFILL;
}
return 0;
}
#define YYCTYPE char
#define YYCURSOR in->cur
#define YYMARKER in->mar
#define YYLIMIT in->lim
#define YYFILL(n) if (fill(in, n) != 0) return 2;
static int lex(input_t *in, long *count, long *total)
{
long c, t;
c = 0; t = 0;
loop:
in->tok = in->cur;
/*!re2c
end = "\x00";
eol = "\n";
crlf = eol;
sp = " ";
htab = "\t";
ows = (sp | htab)*;
digit = [0-9];
alpha = [a-zA-Z];
hexdigit = [0-9a-fA-F];
unreserved = alpha | digit | [-._~];
pct_encoded = "%" hexdigit{2};
sub_delims = [!$&'()*+,;=];
pchar = unreserved | pct_encoded | sub_delims | [:@];
vchar = [\x1f-\x7e];
tchar = [-!#$%&'*+.^_`|~] | digit | alpha;
obs_fold = crlf (sp | htab)+;
obs_text = [\x80-\xff];
field_name = tchar+;
field_vchar = vchar | obs_text;
field_content = field_vchar ((sp | htab)+ field_vchar)?;
field_value = (field_content | obs_fold)*;
header_field = field_name ":" ows field_value ows;
scheme = alpha (alpha | digit | [-+.])*;
userinfo = (unreserved | pct_encoded | sub_delims | ":")*;
dec_octet
= digit
| [\x31-\x39] digit
| "1" digit{2}
| "2" [\x30-\x34] digit
| "25" [\x30-\x35];
ipv4address = dec_octet "." dec_octet "." dec_octet "." dec_octet;
h16 = hexdigit{1,4};
ls32 = h16 ":" h16 | ipv4address;
ipv6address
= (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)? "::";
ipvfuture = "v" hexdigit+ "." (unreserved | sub_delims | ":" )+;
ip_literal = "[" ( ipv6address | ipvfuture ) "]";
reg_name = (unreserved | pct_encoded | sub_delims)*;
path_abempty = ("/" pchar*)*;
path_absolute = "/" (pchar+ ("/" pchar*)*)?;
path_rootless = pchar+ ("/" pchar*)*;
path_empty = "";
host = ip_literal | ipv4address | reg_name;
port = digit*;
query = (pchar | [/?])*;
absolute_uri = scheme ":"
( "//" (userinfo "@")? host (":" port)? path_abempty
| (path_absolute | path_rootless | path_empty)
) ("?" query)?;
authority = (userinfo "@")? host (":" port)?;
origin_form = path_abempty ("?" query)?;
http_name = "HTTP";
http_version = http_name "/" digit "." digit;
request_target
= authority
| absolute_uri
| origin_form
| "*";
method = tchar+;
request_line = method sp request_target sp http_version crlf;
status_code = digit{3};
reason_phrase = (htab | sp | vchar | obs_text)*;
status_line = http_version sp status_code sp reason_phrase crlf;
start_line = (request_line | status_line);
message_head = start_line (header_field crlf)* crlf;
* { return 1; }
end { *count = c; return 0; }
eol { goto loop; }
message_head {
#ifndef VERIFY
c += 1;
t += in->cur - in->tok;
#else
printf("%.*s", (int)(in->cur - in->tok), in->tok);
#endif
goto loop;
}
*/
}
int main(int argc, char **argv)
{
long count, total;
input_t in;
init_input(&in, argv[1]);
switch (lex(&in, &count, &total)) {
case 0: fprintf(stderr, "ok, parsed %ld HTTPs, peeked %ld chars\n", count, total); break;
case 1: fprintf(stderr, "syntax error: %s\n", in.cur); break;
case 2: fprintf(stderr, "fill failed\n"); break;
default: fprintf(stderr, "panic!\n"); break;
}
free_input(&in);
return 0;
}
-6
View File
@@ -1,6 +0,0 @@
. ../../__bench_utils.sh
compile http simple ""
run_all http simple
-6
View File
@@ -1,6 +0,0 @@
. ../../__bench_utils.sh
compile http simple "-b"
run_all http simple
-6
View File
@@ -1,6 +0,0 @@
. ../../__bench_utils.sh
compile http simple "--no-optimize-tags"
run_all http simple
-4
View File
@@ -1,4 +0,0 @@
. ../../__bench_utils.sh
verify http simple
-231
View File
@@ -1,231 +0,0 @@
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct taglist_t {
struct taglist_t *pred;
long dist;
} taglist_t;
typedef struct taglistpool_t {
taglist_t *head;
taglist_t *next;
taglist_t *last;
} taglistpool_t;
typedef struct {
FILE *file;
char *buf;
char *lim;
char *cur;
char *mar;
char *tok;
/*!stags:re2c format = "char *@@;\n"; */
/*!mtags:re2c format = "taglist_t *@@;\n"; */
taglistpool_t tlp;
int eof;
} input_t;
static void taglistpool_clear(taglistpool_t *tlp, input_t *in)
{
tlp->next = tlp->head;
/*!mtags:re2c format = "in->@@ = 0;\n"; */
}
static void taglistpool_init(taglistpool_t *tlp)
{
static const unsigned size = 1024 * 1024;
tlp->head = (taglist_t*)malloc(size * sizeof(taglist_t));
tlp->next = tlp->head;
tlp->last = tlp->head + size;
}
static void taglistpool_free(taglistpool_t *tlp)
{
free(tlp->head);
tlp->head = tlp->next = tlp->last = NULL;
}
static taglist_t *taglistpool_next(taglistpool_t *tlp)
{
if (tlp->next < tlp->last) {
return tlp->next++;
}
const unsigned size = tlp->last - tlp->head;
taglist_t *head = (taglist_t*)malloc(2 * size * sizeof(taglist_t));
memcpy(head, tlp->head, size * sizeof(taglist_t));
free(tlp->head);
tlp->head = head;
tlp->next = head + size;
tlp->last = head + size * 2;
return tlp->next++;
}
static void taglist(taglist_t **ptl, const char *b, const char *t, taglistpool_t *tlp)
{
taglist_t *tl = taglistpool_next(tlp);
tl->pred = *ptl;
tl->dist = t - b;
*ptl = tl;
}
/*!max:re2c*/
static const size_t SIZE = 4096;
static void init_input(input_t *in, const char *fname)
{
in->file = fopen(fname, "r");
in->buf = (char*) malloc(SIZE + YYMAXFILL);
in->lim = in->buf + SIZE;
in->cur = in->lim;
in->mar = in->lim;
in->tok = in->lim;
/*!stags:re2c format = "in->@@ = 0;\n"; */
/*!mtags:re2c format = "in->@@ = 0;\n"; */
taglistpool_init(&in->tlp);
in->eof = 0;
}
static void free_input(input_t *in)
{
fclose(in->file);
free(in->buf);
taglistpool_free(&in->tlp);
}
static int fill(input_t *in, size_t need)
{
size_t free;
if (in->eof) return 1;
free = in->tok - in->buf;
if (free < need) return 2;
memmove(in->buf, in->tok, in->lim - in->tok);
in->lim -= free;
in->cur -= free;
in->mar -= free;
in->tok -= free;
/*!stags:re2c format = "if (in->@@) in->@@ -= free;\n"; */
in->lim += fread(in->lim, 1, free, in->file);
if (in->lim < in->buf + SIZE) {
in->eof = 1;
memset(in->lim, 0, YYMAXFILL);
in->lim += YYMAXFILL;
}
return 0;
}
static void print_headers(const char *tok,
const taglist_t *h1, const taglist_t *h2, const taglist_t *h3)
{
if (!h1 || !h2 || !h3) {
assert(!h1 && !h2 && !h3);
return;
}
print_headers(tok, h1->pred, h2->pred, h3->pred);
printf("%.*s%.*s\n",
(int)(h2->dist - h1->dist), tok + h1->dist,
(int)(h3->dist - h2->dist), tok + h2->dist);
}
#define YYCTYPE char
#define YYCURSOR in->cur
#define YYMARKER in->mar
#define YYLIMIT in->lim
#define YYMTAGP(tl) taglist(&tl, in->tok, in->cur, &in->tlp)
#define YYMTAGN(tl) taglist(&tl, in->tok, NULL, &in->tlp)
#define YYFILL(n) if (fill(in, n) != 0) return 2;
static int lex(input_t *in, long *count, long *total)
{
const char *s1, *s2, *v1, *v2, *v3, *v4, *m1, *m2, *rp1, *rp2, *rt1, *rt2;
taglist_t *h1, *h2, *h3;
long c, t;
c = 0; t = 0;
loop:
in->tok = in->cur;
/*!re2c
re2c:flags:tags = 1;
re2c:tags:expression = "in->@@";
end = "\x00";
eol = "\n";
sp = " ";
htab = "\t";
ows = (sp | htab)*;
char = [-._~%!$&'()*+,;=a-zA-Z0-9];
tchar = [-._~%!$&'*+#^`|a-zA-Z0-9];
vchar = [\x1f-\x7e\x80-\xff];
scheme = [-+.a-zA-Z0-9]+;
userinfo = (char | [:])+;
host = (char | [:[\]])+;
port = [0-9]*;
path = (char | [:@/])*;
query = (char | [:@?/])*;
obs_fold = eol (sp | htab)+;
field_content = vchar ((sp | htab)+ vchar)?;
header_field = #h1 tchar+ ":" #h2 ows (field_content | obs_fold)* ows #h3;
authority = (userinfo "@")? host (":" port)?;
absolute_uri = scheme ":" ("//" (userinfo "@")? host (":" port)?)? path ("?" query)?;
origin_form = "/" path ("?" query)?;
http_version = "HTTP/" [0-9] "." [0-9];
request_target = authority | absolute_uri | origin_form | "*";
method = tchar+;
request_line = @m1 method @m2 sp @rt1 request_target @rt2 sp @v3 http_version @v4 eol;
status_code = [0-9]{3};
reason_phrase = (htab | sp | vchar)*;
status_line = @v1 http_version @v2 sp @s1 status_code @s2 sp @rp1 reason_phrase @rp2 eol;
start_line = (request_line | status_line);
message_head = start_line (header_field eol)* eol;
* { return 1; }
end { *count = c; *total = t; return 0; }
eol { goto loop; }
message_head {
#ifndef VERIFY
c += 1;
t += (v2 - v1) + (s2 - s1) + (rp2 - rp1)
+ (m2 - m1) + (rt2 - rt1) + (v4 - v3);
for (; h1 != 0; h1 = h1->pred, h2 = h2->pred, h3 = h3->pred) {
t += (h2->dist - h1->dist) + (h3->dist - h2->dist);
}
#else
if (s1) printf("%.*s %.*s %.*s\n",
(int)(v2 - v1), v1,
(int)(s2 - s1), s1,
(int)(rp2 - rp1), rp1);
if (m1) printf("%.*s %.*s %.*s\n",
(int)(m2 - m1), m1,
(int)(rt2 - rt1), rt1,
(int)(v4 - v3), v3);
print_headers(in->tok, h1, h2, h3);
printf("\n");
#endif
taglistpool_clear(&in->tlp, in);
goto loop;
}
*/
}
int main(int argc, char **argv)
{
long count, total;
input_t in;
init_input(&in, argv[1]);
switch (lex(&in, &count, &total)) {
case 0: fprintf(stderr, "ok, parsed %ld HTTPs, peeked %ld chars\n", count, total); break;
case 1: fprintf(stderr, "syntax error: %s\n", in.cur); break;
case 2: fprintf(stderr, "fill failed\n"); break;
default: fprintf(stderr, "panic!\n"); break;
}
free_input(&in);
return 0;
}
@@ -1,134 +0,0 @@
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
FILE *file;
char *buf;
char *lim;
char *cur;
char *mar;
char *tok;
int eof;
} input_t;
/*!max:re2c*/
static const size_t SIZE = 4096;
static void init_input(input_t *in, const char *fname)
{
in->file = fopen(fname, "r");
in->buf = (char*) malloc(SIZE + YYMAXFILL);
in->lim = in->buf + SIZE;
in->cur = in->lim;
in->mar = in->lim;
in->tok = in->lim;
in->eof = 0;
}
static void free_input(input_t *in)
{
fclose(in->file);
free(in->buf);
}
static int fill(input_t *in, size_t need)
{
size_t free;
if (in->eof) return 1;
free = in->tok - in->buf;
if (free < need) return 2;
memmove(in->buf, in->tok, in->lim - in->tok);
in->lim -= free;
in->cur -= free;
in->mar -= free;
in->tok -= free;
in->lim += fread(in->lim, 1, free, in->file);
if (in->lim < in->buf + SIZE) {
in->eof = 1;
memset(in->lim, 0, YYMAXFILL);
in->lim += YYMAXFILL;
}
return 0;
}
#define YYCTYPE char
#define YYCURSOR in->cur
#define YYMARKER in->mar
#define YYLIMIT in->lim
#define YYFILL(n) if (fill(in, n) != 0) return 2;
static int lex(input_t *in, long *count, long *total)
{
long c, t;
c = 0; t = 0;
loop:
in->tok = in->cur;
/*!re2c
end = "\x00";
eol = "\n";
sp = " ";
htab = "\t";
ows = (sp | htab)*;
char = [-._~%!$&'()*+,;=a-zA-Z0-9];
tchar = [-._~%!$&'*+#^`|a-zA-Z0-9];
vchar = [\x1f-\x7e\x80-\xff];
scheme = [-+.a-zA-Z0-9]+;
userinfo = (char | [:])+;
host = (char | [:[\]])+;
port = [0-9]*;
path = (char | [:@/])*;
query = (char | [:@?/])*;
obs_fold = eol (sp | htab)+;
field_content = vchar ((sp | htab)+ vchar)?;
header_field = tchar+ ":" ows (field_content | obs_fold)* ows;
authority = (userinfo "@")? host (":" port)?;
absolute_uri = scheme ":" ("//" (userinfo "@")? host (":" port)?)? path ("?" query)?;
origin_form = "/" path ("?" query)?;
http_version = "HTTP/" [0-9] "." [0-9];
request_target = authority | absolute_uri | origin_form | "*";
method = tchar+;
request_line = method sp request_target sp http_version eol;
status_code = [0-9]{3};
reason_phrase = (htab | sp | vchar)*;
status_line = http_version sp status_code sp reason_phrase eol;
start_line = (request_line | status_line);
message_head = start_line (header_field eol)* eol;
* { return 1; }
end { *count = c; *total = t; return 0; }
eol { goto loop; }
message_head {
#ifndef VERIFY
c += 1;
t += in->cur - in->tok;
#else
printf("%.*s", (int)(in->cur - in->tok), in->tok);
#endif
goto loop;
}
*/
}
int main(int argc, char **argv)
{
long count, total;
input_t in;
init_input(&in, argv[1]);
switch (lex(&in, &count, &total)) {
case 0: fprintf(stderr, "ok, parsed %ld HTTPs, peeked %ld chars\n", count, total); break;
case 1: fprintf(stderr, "syntax error: %s\n", in.cur); break;
case 2: fprintf(stderr, "fill failed\n"); break;
default: fprintf(stderr, "panic!\n"); break;
}
free_input(&in);
return 0;
}
+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
File diff suppressed because it is too large Load Diff
@@ -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
@@ -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
File diff suppressed because one or more lines are too long
@@ -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);
}
}

Some files were not shown because too many files have changed in this diff Show More