]> granicus.if.org Git - re2c/log
re2c
9 years ago'--skeleton': fixed codegen error with '-b' (don't forget last bitmap element).
Ulya Trofimovich [Wed, 30 Sep 2015 15:12:27 +0000 (16:12 +0100)]
'--skeleton': fixed codegen error with '-b' (don't forget last bitmap element).

9 years ago'--skeleton': added missing newline in the generated code.
Ulya Trofimovich [Wed, 30 Sep 2015 15:11:45 +0000 (16:11 +0100)]
'--skeleton': added missing newline in the generated code.

9 years ago'--skeleton': tell function name when reporting errors and warnings.
Ulya Trofimovich [Wed, 30 Sep 2015 15:10:38 +0000 (16:10 +0100)]
'--skeleton': tell function name when reporting errors and warnings.

9 years ago'--skeleton': respect empty string match.
Ulya Trofimovich [Tue, 29 Sep 2015 15:47:25 +0000 (16:47 +0100)]
'--skeleton': respect empty string match.

9 years agoFixed skeleton generation in '-r' mode.
Ulya Trofimovich [Tue, 29 Sep 2015 15:04:27 +0000 (16:04 +0100)]
Fixed skeleton generation in '-r' mode.

'-r' is different from normal mode in two aspects:
    - single DFA may be used multiple times (unchanged, we only
      need a single copy for skeleton)
    - DFA may be generated but not used at all

9 years agoSplit skeleton arc count limits for permutations, cover and default paths.
Ulya Trofimovich [Mon, 28 Sep 2015 21:34:06 +0000 (22:34 +0100)]
Split skeleton arc count limits for permutations, cover and default paths.

9 years agoDocs: updated descriptions of some inplace configurations.
Ulya Trofimovich [Mon, 28 Sep 2015 14:30:20 +0000 (15:30 +0100)]
Docs: updated descriptions of some inplace configurations.

9 years agoUnified meaning and mutual relations of some inplace configurations.
Ulya Trofimovich [Mon, 28 Sep 2015 12:54:26 +0000 (13:54 +0100)]
Unified meaning and mutual relations of some inplace configurations.

This commit changes the behaviour of three groups of options:

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

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

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

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

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

Added test generator and autogenerated tests.

9 years agorun_tests.sh: preserve nested directory structure when dumping errors.
Ulya Trofimovich [Mon, 28 Sep 2015 12:49:05 +0000 (13:49 +0100)]
run_tests.sh: preserve nested directory structure when dumping errors.

9 years agoDon't hang forever trying to replace empty configuration arguments.
Ulya Trofimovich [Sun, 27 Sep 2015 11:03:03 +0000 (12:03 +0100)]
Don't hang forever trying to replace empty configuration arguments.

9 years agoDefault options should be syncronized as well.
Ulya Trofimovich [Sun, 27 Sep 2015 10:58:40 +0000 (11:58 +0100)]
Default options should be syncronized as well.

9 years agoReduced redundant global flags.
Ulya Trofimovich [Thu, 24 Sep 2015 14:21:45 +0000 (15:21 +0100)]
Reduced redundant global flags.

9 years agoHandle all inplace configurations in a uniform way.
Ulya Trofimovich [Thu, 24 Sep 2015 13:52:24 +0000 (14:52 +0100)]
Handle all inplace configurations in a uniform way.

This commit removes check (and error) for overwritten configurations
(like setting 're2c:define:YYCYRSOR' twice in the same block).
This check was in principle useful, but it was applied to somehow
randomly chosen set of parameters. If in future we'll feel a need
for such check, it should respect all options equally and report
warning rather than error.

9 years agoAutomatically resync options on read acccess (if they have been updated).
Ulya Trofimovich [Wed, 23 Sep 2015 21:08:39 +0000 (22:08 +0100)]
Automatically resync options on read acccess (if they have been updated).

9 years agoMerged 'DFlag' and 'flag_skeleton' into one option 'target'.
Ulya Trofimovich [Wed, 23 Sep 2015 16:32:36 +0000 (17:32 +0100)]
Merged 'DFlag' and 'flag_skeleton' into one option 'target'.

The nature of these options makes them mutually exclusive; so instead
of checking that they are not both set just make them a single option.

9 years agoSeparated user config and effective config.
Ulya Trofimovich [Wed, 23 Sep 2015 14:45:54 +0000 (15:45 +0100)]
Separated user config and effective config.

9 years agoPrepare to separate user config and effective config.
Ulya Trofimovich [Tue, 22 Sep 2015 12:15:31 +0000 (13:15 +0100)]
Prepare to separate user config and effective config.

9 years agoKeep name table together with other options.
Ulya Trofimovich [Mon, 21 Sep 2015 21:14:45 +0000 (22:14 +0100)]
Keep name table together with other options.

9 years agoGrouped options together in a struct.
Ulya Trofimovich [Mon, 21 Sep 2015 20:50:55 +0000 (21:50 +0100)]
Grouped options together in a struct.

9 years agoDocumentation: added warning descriptions to manpage and online manual.
Ulya Trofimovich [Thu, 17 Sep 2015 14:16:38 +0000 (15:16 +0100)]
Documentation: added warning descriptions to manpage and online manual.

9 years agoDocumentation: added warning descriptions to '-h, -?, --help' option.
Ulya Trofimovich [Thu, 17 Sep 2015 14:03:24 +0000 (15:03 +0100)]
Documentation: added warning descriptions to '-h, -?, --help' option.

9 years agoRemoved unused method declaration.
Ulya Trofimovich [Thu, 17 Sep 2015 12:55:46 +0000 (13:55 +0100)]
Removed unused method declaration.

9 years agoGather some DFA statistics and use it to omit unused code with '--skeleton'.
Ulya Trofimovich [Thu, 17 Sep 2015 12:52:09 +0000 (13:52 +0100)]
Gather some DFA statistics and use it to omit unused code with '--skeleton'.

9 years agoOmit usseless 'yyaccept' variable in '--skeleton' programs.
Ulya Trofimovich [Thu, 17 Sep 2015 09:53:35 +0000 (10:53 +0100)]
Omit usseless 'yyaccept' variable in '--skeleton' programs.

Normally re2c generates single 'yyaccept' variable for all conditions.
With '--skeleton' re2c handles conditions separately, so each condition
needs (or needs not) its own 'yyaccept'.

Prior to this commit re2c used the same criterion to determine if
'yyaccept' is needed with '--skeleton' as it uses generally: whether
'yyaccept' was used in any of conditions. Now re2c looks if 'yyaccept'
was used with this particular condition.

9 years agoGenerate better code with '--skeleton': C90-compliant, free resources on errors.
Ulya Trofimovich [Thu, 17 Sep 2015 09:27:57 +0000 (10:27 +0100)]
Generate better code with '--skeleton': C90-compliant, free resources on errors.

9 years agoCheck 'fread' return value in program generated with '--skeleton'.
Ulya Trofimovich [Wed, 16 Sep 2015 11:19:28 +0000 (12:19 +0100)]
Check 'fread' return value in program generated with '--skeleton'.

9 years agoSupport '--skeleton' with conditions and multiple re2c blocks.
Ulya Trofimovich [Wed, 16 Sep 2015 10:25:29 +0000 (11:25 +0100)]
Support '--skeleton' with conditions and multiple re2c blocks.

9 years agoMake 'filesize' function for '--skeleton' preserve original file position.
Ulya Trofimovich [Tue, 15 Sep 2015 12:35:27 +0000 (13:35 +0100)]
Make 'filesize' function for '--skeleton' preserve original file position.

9 years agoFixed MINGW builds where 'sizeof (int)' is equal to 'sizeof (long)'.
Ulya Trofimovich [Tue, 15 Sep 2015 12:08:10 +0000 (13:08 +0100)]
Fixed MINGW builds where 'sizeof (int)' is equal to 'sizeof (long)'.

9 years agoChanged '-Wcondition-order' to warn even if 'YYSETCONDITION' is used.
Ulya Trofimovich [Tue, 15 Sep 2015 10:51:36 +0000 (11:51 +0100)]
Changed '-Wcondition-order' to warn even if 'YYSETCONDITION' is used.

Tests 'condtype_yysetcondition.c{s,g}.re' show the reason why I changed
how '-Wcondition-order' works in presence of 'YYSETCONDITION' calls:
programs generated from these tests work differently depending on
condition numbering. Explicit use of condition names cannot guarantee
that these explicit names were generated by re2c (and not hardcoded as
in these examples).

9 years agoMore accurate handling of default rule for '--skeleton'.
Ulya Trofimovich [Tue, 15 Sep 2015 09:45:19 +0000 (10:45 +0100)]
More accurate handling of default rule for '--skeleton'.

9 years agoThe generated '--skeleton' program now warns about undefined control flow.
Ulya Trofimovich [Mon, 14 Sep 2015 22:11:51 +0000 (23:11 +0100)]
The generated '--skeleton' program now warns about undefined control flow.

9 years agoFixed error in calculation of maximal path length in skeleton.
Ulya Trofimovich [Mon, 14 Sep 2015 14:28:52 +0000 (15:28 +0100)]
Fixed error in calculation of maximal path length in skeleton.

9 years agoCompacted keys representation (with '--skeleton').
Ulya Trofimovich [Mon, 14 Sep 2015 12:19:15 +0000 (13:19 +0100)]
Compacted keys representation (with '--skeleton').

Determine maximal path length and maximal rule number while constructing
skeleton; take maximim of these two values; choose unsigned integer type
of minimal width capable of holding maximim.

Note: re2c operates on exact-width integers, but the generated program
doesn't (it might not have <stdint.h>). When generating the program,
re2c choses one of unsigned 'char', 'short', 'int' and 'long' types
(that one 'sizeof' which is equal to the disired key size). re2c makes
some implicit assumptions (generated program is run on the same platform
as re2c, byte consists of 8 bits, etc.). Perhaps re2c should hardcode
these assumptions in the generated program and check them on start.

9 years agoStore keys for '--skeleton' in binary.
Ulya Trofimovich [Fri, 11 Sep 2015 17:48:35 +0000 (18:48 +0100)]
Store keys for '--skeleton' in binary.

A single key is formed of three values:
    1. the length of string
    2. the length of matched part of string
    3. the number of matched rule
All these values are guaranteed to fit 32 bits, so for now we just
dump them as 'uint32_t' and read as 'unsigned int'. re2c asserts that
'sizeof (uint32_t) == sizeof (unsigned int)'.

Avoid structs, as they cause padding issues.

9 years agoEstimate maximal path length in skeleton and abort if it overflows.
Ulya Trofimovich [Wed, 9 Sep 2015 21:43:31 +0000 (22:43 +0100)]
Estimate maximal path length in skeleton and abort if it overflows.

Maximal skeleton path length is a bit different from YYMAXFILL:
it assumes that loops are iterated once (unlike YYMAXFILL calculation,
which disregards loops) and returns zero for empty regexp.

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

This commit also makes DFA and skeleton store condition name and
source file line corresponding to current condition: it gets quite
annoying to pass these things around. This change caused another
change of test results (line numbers in error messages changed
for tests that use '-r' and reuse old DFA (don't reconstruct DFA
in 'use:re2c' blocks).

9 years agoFixed memleaks (skeleton nodes were not destructed properly).
Ulya Trofimovich [Wed, 9 Sep 2015 15:26:28 +0000 (16:26 +0100)]
Fixed memleaks (skeleton nodes were not destructed properly).

Found with 'make vtests'

9 years agoMake skeleton a part of DFA.
Ulya Trofimovich [Wed, 9 Sep 2015 14:30:09 +0000 (15:30 +0100)]
Make skeleton a part of DFA.

This let us create skeletom right after DFA creation (but befor DFA
has been mangled in different ways), but call skeleton methods any time.

Undefined control flow is now checked at the time of real code generation,
that's why all those tests that use '-r' changed: re2c stopped reporting
'rules:re2c' blocks and reports 'use:re2c' blocks instead.

9 years agoSuffixes of skeleton end nodes should be initialized by algorithm that uses them.
Ulya Trofimovich [Wed, 9 Sep 2015 12:09:25 +0000 (13:09 +0100)]
Suffixes of skeleton end nodes should be initialized by algorithm that uses them.

9 years agoRenamed function.
Ulya Trofimovich [Tue, 8 Sep 2015 16:57:06 +0000 (17:57 +0100)]
Renamed function.

9 years agoA more logical way to update rules when constructing skeleton paths.
Ulya Trofimovich [Tue, 8 Sep 2015 16:33:34 +0000 (17:33 +0100)]
A more logical way to update rules when constructing skeleton paths.

There's no need to keep rule one step behind path's arcs and update
it manually. Also, it is reasonable to set rule in constructor.

9 years agoReduced the time of path generation with '--skeleton'.
Ulya Trofimovich [Tue, 8 Sep 2015 14:14:09 +0000 (15:14 +0100)]
Reduced the time of path generation with '--skeleton'.

The algorithm now stores partially constructed paths in a compact
form and delays expansion until it reaches the end of current
branch of recursion. This has several advantages:
    - no need to store large structures in memory
    - write data to file in large chunks
    - path expansion is faster than step-by-step construction

Speedup is actually tenfold (but the way keys are dumped to file is
still not optimized and spoils benchmarks). Real speedup can be
observed on such files as:
    test/php20150211_zend_ini_scanner_trimmed.icF.re
, which cause ~5Gb dumps. Time has gone down: 8.5m -> 2.5m and will
be furter reduced to ~1m when key dumps are fixed. This will result
in generation speed ~20Mb/s which is quite good.

9 years agoRenamed and restructured various kinds of skeleton paths.
Ulya Trofimovich [Tue, 8 Sep 2015 11:06:52 +0000 (12:06 +0100)]
Renamed and restructured various kinds of skeleton paths.

9 years agoFixed eternal loop in path cover generation algorithm for '--skeleton'.
Ulya Trofimovich [Sun, 6 Sep 2015 21:22:12 +0000 (22:22 +0100)]
Fixed eternal loop in path cover generation algorithm for '--skeleton'.

The simplest example I was able to come up with that reveals eternal
loop is the following:
    /*!re2c
        ( [^acf] | "0b" | "a"[^] | "a0"[^] )+ {}
    */
The problem was caused by my assumption that from any node there is
at least one non-looping path to end node. The assumption is true;
what I didn't take into account was that all such paths may go via
nodes that have already occured twice on the way to current node
(their loop counter is greater than 1). In this case the algorithm
would find no path to end node. Since not all prefixes would have
been covered (exactly none of them) the algorithm would loop forever.

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

As soon as I realized the problem the fix was trivial: if all outgoing
arcs have been exhausted and none of them yielded any results, abandon
current branch.

9 years agoWith '--skeleton', store input data in binary form (rather than C/C++ code).
Ulya Trofimovich [Sat, 5 Sep 2015 08:39:28 +0000 (09:39 +0100)]
With '--skeleton', store input data in binary form (rather than C/C++ code).

There's a limitation on the size of input files for C/C++ compiler and
the compiled binary will have to contain all that data (and thus may grow
very large).

Storing data in binary form and reading it from file dynamically is
the way it should be.

9 years agoWith '-skeleton', dump data to file immediately as it is generated.
Ulya Trofimovich [Fri, 4 Sep 2015 14:07:06 +0000 (15:07 +0100)]
With '-skeleton', dump data to file immediately as it is generated.

This way re2c won't consume memory even on large inputs.

9 years agoChanged '.keys' file format (generated with '--skeleton').
Ulya Trofimovich [Thu, 3 Sep 2015 14:18:45 +0000 (15:18 +0100)]
Changed '.keys' file format (generated with '--skeleton').

Store length of strings instead of pointers to string start and end.

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

This adds a new local variable to the generated code ('token'), which
is used to backup cursor position when enterind DFA.

9 years agoSplit ".data" files (generated with '--skeleton') into two parts.
Ulya Trofimovich [Thu, 3 Sep 2015 12:26:47 +0000 (13:26 +0100)]
Split ".data" files (generated with '--skeleton') into two parts.

This is necessary to dump generated data as soon as possible instead
of keeping it until all data has been generated: we generate input
strings and keys simultaneously, but have to write all input strings
at once as one big string. Keys alone occupy lots of space, so
keeping only keys instead of keys and strings won't help.

9 years agoCombined path cover generation with path cover size estimation.
Ulya Trofimovich [Thu, 3 Sep 2015 11:33:02 +0000 (12:33 +0100)]
Combined path cover generation with path cover size estimation.

We don't have any fallback algorithm in case path cover is too large.
We want to generate some paths anyway, so we have to construct path cover.
We shouldn't generate arbitrary large amounts of data.

9 years agoOmit some highly unlikely conditional exits from deep-first search.
Ulya Trofimovich [Wed, 2 Sep 2015 12:28:48 +0000 (13:28 +0100)]
Omit some highly unlikely conditional exits from deep-first search.

With '--skeleton' re2c builds DFA skeleton and performs DFS in order to
estimate the size of data to be generated. It maintains size counter: as
soon as the counter reaches certain limit, DFS should stop.

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

This commit omits checks of some arguments (and correponding early exits
from DFS): first, path length is very unlikely to overflow (one has to
write/generate a regular expression with length of ~1Gb, in which case
skeleton generation won't be the worst problem); second, the number of
outgoing arcs in each vertex is also highly unlikely to exceed 1Gb limit.

9 years agoSplit large source file into smaller files with distinct functionality.
Ulya Trofimovich [Wed, 2 Sep 2015 12:11:36 +0000 (13:11 +0100)]
Split large source file into smaller files with distinct functionality.

9 years agoNarrowed the scope of ".data" file.
Ulya Trofimovich [Wed, 2 Sep 2015 11:39:47 +0000 (12:39 +0100)]
Narrowed the scope of ".data" file.

9 years agoHid internals of skeleton paths under construction.
Ulya Trofimovich [Wed, 2 Sep 2015 10:44:25 +0000 (11:44 +0100)]
Hid internals of skeleton paths under construction.

9 years agoRenamed and fixed warning about undefined control flow in generated lexer.
Ulya Trofimovich [Tue, 1 Sep 2015 14:27:48 +0000 (15:27 +0100)]
Renamed and fixed warning about undefined control flow in generated lexer.

Renamed '-Wnaked-default' to '-Wundefined-control-flow': the latter sounds
much scarier. :D

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

The new algorithm is more complex (in terms of time and space), yet it is
less heuristic: re2c parforms exhaustive deep-first-search on graph skeleton
and collects all bad paths.

9 years agoNo need to NULL-terminate array of known size.
Ulya Trofimovich [Fri, 28 Aug 2015 22:15:40 +0000 (23:15 +0100)]
No need to NULL-terminate array of known size.

For some reason (which I yet do not understand) re2c uses size of DFA
state's "kernel" to determine whether a new state should be constructed
or some already constructed state (of the same "kernel" size) will do.

Since re2c knows "kernel" size for each state anyway, there's no need
to NULL-terminate "kernel" array while iterating over it: we can use
pre-calculated size instead.

9 years agoNarrowed scope of local variables.
Ulya Trofimovich [Fri, 28 Aug 2015 22:10:33 +0000 (23:10 +0100)]
Narrowed scope of local variables.

9 years agoSimplified array bounds check.
Ulya Trofimovich [Fri, 28 Aug 2015 22:00:56 +0000 (23:00 +0100)]
Simplified array bounds check.

Comparing against pointer to the end of array is easier than calculating
array length, then setting next-to-last element to NULL and iterating
while not NULL.

9 years agoAnother minor simplification of control flow.
Ulya Trofimovich [Fri, 28 Aug 2015 21:33:51 +0000 (22:33 +0100)]
Another minor simplification of control flow.

9 years agoClarified control flow in nested loops.
Ulya Trofimovich [Fri, 28 Aug 2015 21:03:51 +0000 (22:03 +0100)]
Clarified control flow in nested loops.

9 years agoNarrowed scope of local variables.
Ulya Trofimovich [Fri, 28 Aug 2015 20:52:28 +0000 (21:52 +0100)]
Narrowed scope of local variables.

9 years agoPass signed integer to 'std::setw' to avoid [-Wsign-conversion] warning.
Ulya Trofimovich [Fri, 28 Aug 2015 14:09:35 +0000 (15:09 +0100)]
Pass signed integer to 'std::setw' to avoid [-Wsign-conversion] warning.

9 years agoDon't mix up empty code block with nonexistent one in rule actions.
Ulya Trofimovich [Thu, 27 Aug 2015 22:30:03 +0000 (23:30 +0100)]
Don't mix up empty code block with nonexistent one in rule actions.

Turns out that re2c allows empty code blocks:
    /*!re2c
    <a> "a" :=
    */

re2c up to 0.14.3 handled this correctly (generated empty action).
Since then this behaviour has been broken: re2c started to autogenerate
jump to nonexistent condition.

9 years agoDelay '-Wcondition-order' reporting until we have necessary info.
Ulya Trofimovich [Thu, 27 Aug 2015 13:03:26 +0000 (14:03 +0100)]
Delay '-Wcondition-order' reporting until we have necessary info.

'-Wcondition-order' depends on 'YYSETCONDITION' calls and 'types:re2c'
directive which may occur after condition dispatch is generated.

9 years agoAdded warning '-Wcondition-order'.
Ulya Trofimovich [Thu, 27 Aug 2015 11:42:24 +0000 (12:42 +0100)]
Added warning '-Wcondition-order'.

See parent commit 8c1fe4f0113685b599bf906360814e4715e05447
"Simplified tracking of condition order." for details.

9 years agoSimplified tracking of condition order.
Ulya Trofimovich [Wed, 26 Aug 2015 11:41:48 +0000 (12:41 +0100)]
Simplified tracking of condition order.

In theory re2c makes no guarantee about the order of conditions in
the generated lexer. Users should use 'YYGETCONDITION'/'YYSETCONDITION'
interface and generate enum with condition names using either '-t'
option or '/*!types:re2c*/' directive. Only members of the generated
enum should be used with 'YYGETCONDITION' and 'YYSETCONDITION'.
This way code is independent of internal re2c condition numbering.

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

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

This commit tries to simplify tracking of condition numbers.

9 years agoFixed bug #119: "-f with -b/-g generates incorrect dispatch on fill labels".
Ulya Trofimovich [Tue, 25 Aug 2015 10:33:29 +0000 (11:33 +0100)]
Fixed bug #119: "-f with -b/-g generates incorrect dispatch on fill labels".

Consider the following example 1.re:
    /*!re2c
        "" {}
    */
With -if, re2c would generate correct dispatch:
    $ re2c -if 1.re
    /* Generated by re2c 0.14.3 on Tue Aug 25 10:41:45 2015 */
            switch (YYGETSTATE()) {
            default: goto yy0;
            case 0: goto yyFillLabel0;
            }
    yy0:
            YYSETSTATE(0);
    yyFillLabel0:
            {}

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

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

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

Fix: always generate simple switch.

9 years agoMakefile.am: update bootstrap parser when necessary.
Ulya Trofimovich [Mon, 24 Aug 2015 13:38:16 +0000 (14:38 +0100)]
Makefile.am: update bootstrap parser when necessary.

The mechanism of updating bootstrap parser was broken by commit
b2bc24704ebd2a0e6050f755dbd93a5cd987a418 : "Support 'make distcheck'."

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

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

This commit makes use of two observations:
    - bootstrap parser depends on the source parser, not on the autogenerated
      parser;
    - bootstrap parser shouldn't at all contain line information: at the time
      it is copied to build directory the relative path from build directory
      to source directory may be completely different (as it is with 'make
      distcheck');

9 years agodistcheck.sh can only run from top source directory.
Ulya Trofimovich [Mon, 24 Aug 2015 12:23:55 +0000 (13:23 +0100)]
distcheck.sh can only run from top source directory.

9 years agoExplicit cast of signed nonnegative to unsigned (found with [-Wsign-conversion]).
Ulya Trofimovich [Mon, 24 Aug 2015 09:59:44 +0000 (10:59 +0100)]
Explicit cast of signed nonnegative to unsigned (found with [-Wsign-conversion]).

9 years agoParse configuration strings in the same way as character strings and classes.
Ulya Trofimovich [Sun, 23 Aug 2015 10:34:13 +0000 (11:34 +0100)]
Parse configuration strings in the same way as character strings and classes.

re2c allows configuration strings to contain escape sequencs as long
as the escaped code points fit into 1-byte range.

Finally both 'Scanner::unescape' functions can be removed along with
a whole bunch of [-Wsign-conversion] warnings. :)

9 years agoTests: simple tests for parsing inplace configurations.
Ulya Trofimovich [Sat, 22 Aug 2015 14:52:27 +0000 (15:52 +0100)]
Tests: simple tests for parsing inplace configurations.

Tests do not ensure that configurations are handled correctly or
have any impact on re2c behaviour. They only ensure that these
configuration names are recognized as valid.

9 years agoParse inplace configuration names in lexer.
Ulya Trofimovich [Sat, 22 Aug 2015 13:49:17 +0000 (14:49 +0100)]
Parse inplace configuration names in lexer.

Make re2c do all the dirty work instead of barely recognizing
configuration-like lexeme and manually matching the lexeme against
all allowed configuration names.

This commit adds many new tokens, which means that re2c-generated lexer
and bison-generated parser have both become larger. The difference
is not as great as one might expect: ~60 Kb -> ~80 Kb in both cases.

9 years agoZero-extend code units when casing them from 'signed char' to 'uint32_t'.
Ulya Trofimovich [Thu, 20 Aug 2015 12:24:42 +0000 (13:24 +0100)]
Zero-extend code units when casing them from 'signed char' to 'uint32_t'.

The problem starts with lexer: it should operate on unsigned chars
(as re2c wants). Then these casts won't be needed at all. Mixing
signed and unsigned chars is bad and lexer should be rewritten to
use unsigned chars.

9 years agoForbid newline in strings and character classes.
Ulya Trofimovich [Thu, 20 Aug 2015 12:05:07 +0000 (13:05 +0100)]
Forbid newline in strings and character classes.

Like C language, re2c allows all characters of current charset excapt for
newline and backslash to apper unescaped in string and class literals.

Added tests:
    - all possible characters in strings and classes (omitting
      newline, escaping backslash and quotes/closing bracket)
      with different encodings (re2c up to 0.14.x would segfault
      on this test with '-u' and '-w')
    - string with newline
    - string with unescaped backslash followed by newline (so that
      it won't stick to next character)

9 years agoTests: code points that exceed maximum for current encoding.
Ulya Trofimovich [Thu, 20 Aug 2015 11:35:47 +0000 (12:35 +0100)]
Tests: code points that exceed maximum for current encoding.

Test changes introduced by commit 0346d1666f58da5dbe35d156e0487d95354153ff:
"Check if code point exceeds maximum. Correctly cast 'char' to 'uint32_t'."

9 years agoCheck if code point exceeds maximum. Correctly cast 'char' to 'uint32_t'.
Ulya Trofimovich [Thu, 20 Aug 2015 11:09:52 +0000 (12:09 +0100)]
Check if code point exceeds maximum. Correctly cast 'char' to 'uint32_t'.

First fix:
re2c used to check if code point exceeds maximal value for current
encoding when parsing it. When I moved parsing code points to lexer
I forgot the check.

Second fix:
I assumed that 'static_cast<uint32_t>' on 'signed char' zero-extends.
But I was wrong: it sign-extends. Need to cast to 'unsigned char'
instead.

9 years agoParse unquoted flex-like strings in lexer.
Ulya Trofimovich [Wed, 19 Aug 2015 17:49:28 +0000 (18:49 +0100)]
Parse unquoted flex-like strings in lexer.

Such strings can only contain ASCII letters, digits and uderscore:
no escapes. So there's very little parsing to do: just map code units
directly to code points.

9 years agoParse character strings in lexer.
Ulya Trofimovich [Wed, 19 Aug 2015 17:31:04 +0000 (18:31 +0100)]
Parse character strings in lexer.

This commit is a continuation of e42f271e4b284cd6ed590dc06a5239ce13942fc5:
"Parse character classes in lexer." It makes lexer parse individual code
points instead of barely recognizing string of code points.

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

Note that re2c allows any 1-byte code points. Maybe we should report
non-ASCII or non-printables.

9 years agoRemoved unused function.
Ulya Trofimovich [Tue, 18 Aug 2015 21:11:58 +0000 (22:11 +0100)]
Removed unused function.

9 years agoAdded warning '-Wuseless-escape'.
Ulya Trofimovich [Tue, 18 Aug 2015 20:57:32 +0000 (21:57 +0100)]
Added warning '-Wuseless-escape'.

This is to warn about escaped printable ASCII characters that
shouldn't be escaped in the current context (e.g. quotes inside of
a character class).

9 years agoAdded warning '-Wswapped-range'.
Ulya Trofimovich [Tue, 18 Aug 2015 16:14:45 +0000 (17:14 +0100)]
Added warning '-Wswapped-range'.

When re2c parses character class and finds a range with lower bound
greater than upper bound, it silently swaps bounds. Warn about such
cases.

9 years agoParse character classes in lexer.
Ulya Trofimovich [Tue, 18 Aug 2015 14:54:22 +0000 (15:54 +0100)]
Parse character classes in lexer.

Before this commit, lexer would barely recognize class as a whole
lexeme and pass it to functions that would further parse is by manually
picking individual code points and control characters out of the lexeme.

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

I tried to preserve existing behaviour (judging from test suite only
the text of some error messages has changed). Added some autogenerated
tests (and the generator script itself), but these tests are not exhaustive.

9 years agoLexer: no need to have "{0,}" special case.
Ulya Trofimovich [Sun, 16 Aug 2015 19:57:29 +0000 (20:57 +0100)]
Lexer: no need to have "{0,}" special case.

Now "{0,}" is handled by general case for counted repetition. Had to
fix test because of swapped alternatives in construction of regexps
of the form "r*" and "r{n,".

Added some tests for counted repetition.

9 years agoRestored explicit cast that was removed in 7af5d437e49878ea4e8de73a02d99ad4e5751933.
Ulya Trofimovich [Sun, 16 Aug 2015 19:14:50 +0000 (20:14 +0100)]
Restored explicit cast that was removed in 7af5d437e49878ea4e8de73a02d99ad4e5751933.

Found with [-Wsign-compare] while building with MINGW: pointer
difference is of different size on linux and windows.

9 years agoForce definition of some conditionally defined parts of <stdint.h>.
Ulya Trofimovich [Sun, 16 Aug 2015 19:02:04 +0000 (20:02 +0100)]
Force definition of some conditionally defined parts of <stdint.h>.

Got some errors about undefined 'UINT32_MAX' and others while trying
to build re2c with MINGW. These variables are defined conditionally in
<stdint.h> depending on the following defines:
    __STDC_LIMIT_MACROS
    __STDC_CONSTANT_MACROS
Fix: defined these symbols in the beginning of "src/util/c99_stdint.h".

Also found out that "src/util/c99_stdint.h" didn't compile in the
absense of system <stdint.h> (which is exactly the case when it was
written for). THe problem was caused by incorrect use of 'typedef'
statement; fixed easily. What a shame I didn't compile it before ;D

9 years agoFixed [-Wsign-conversion] warnings in 'testrange' sources.
Ulya Trofimovich [Sun, 16 Aug 2015 14:21:23 +0000 (15:21 +0100)]
Fixed [-Wsign-conversion] warnings in 'testrange' sources.

9 years agoUse custom function instead of 'atoi' to read 32-bit integers.
Ulya Trofimovich [Sun, 16 Aug 2015 11:08:21 +0000 (12:08 +0100)]
Use custom function instead of 'atoi' to read 32-bit integers.

Using 'atoi' displeased me for several reasons:
    - 'atoi' doesn't check for overflow
    - by the time 'atoi' was called, re2c has already parsed input
      string and knows that it is well-formed, no need to do it twice
    - atoi returns 'int', custom function allows to refine types and
      avoid casts between signed/unsigned values or [-Wsign-conversion]
      warnings

Added test for new conversion functions.

9 years agoDon't use special regexp type for counted repetitions.
Ulya Trofimovich [Sat, 15 Aug 2015 16:42:41 +0000 (17:42 +0100)]
Don't use special regexp type for counted repetitions.

Counted repetitions are regexps of the form:
    r{n}
    r{n,m}
    r{n,}

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

Reducing special regexp type to represent counted repetitions allows
us substitute complex code that compiles them to bytecode instructions
with simpler code that constructs counted repetitions using concatenation,
alternation and iteration.

9 years agoRemoved unused struct field.
Ulya Trofimovich [Sat, 15 Aug 2015 15:22:28 +0000 (16:22 +0100)]
Removed unused struct field.

9 years agoStore lexer buffer size inside of lexer class.
Ulya Trofimovich [Fri, 14 Aug 2015 13:37:12 +0000 (14:37 +0100)]
Store lexer buffer size inside of lexer class.

9 years agoSome more explicit casts in lexer fill procedure (found with [-Wsign-conversion]).
Ulya Trofimovich [Fri, 14 Aug 2015 13:29:19 +0000 (14:29 +0100)]
Some more explicit casts in lexer fill procedure (found with [-Wsign-conversion]).

Lexer tries to maintain certain layout of pointers to buffer.
Buffer refilling procedure relies on that layout.

9 years agoLexer: unified token length calculation.
Ulya Trofimovich [Fri, 14 Aug 2015 12:57:58 +0000 (13:57 +0100)]
Lexer: unified token length calculation.

Token length equals the difference between two pointers: YYCURSOR
value on the moment of successful match and YYCURSOR value when
entering DFA. This difference should be nonnegative and fit buffer
size.

9 years agoUse different local variables for unrelated tasks.
Ulya Trofimovich [Fri, 14 Aug 2015 12:57:31 +0000 (13:57 +0100)]
Use different local variables for unrelated tasks.

9 years agoFixed '#27 re2c crashes reading files containing %{ %}' (patch by Rui)
Ulya Trofimovich [Wed, 12 Aug 2015 21:32:24 +0000 (22:32 +0100)]
Fixed '#27 re2c crashes reading files containing %{ %}' (patch by Rui)

merged commit b068f3ad2ea7b01aa1eb63cb655c3357f856e85b from master.

9 years agoLexer: reduced unnecessary macro.
Ulya Trofimovich [Wed, 12 Aug 2015 17:50:38 +0000 (18:50 +0100)]
Lexer: reduced unnecessary macro.

9 years agoLexer: glued together two variables with almost identical functionality.
Ulya Trofimovich [Wed, 12 Aug 2015 16:39:21 +0000 (17:39 +0100)]
Lexer: glued together two variables with almost identical functionality.

These two variables ('ScannerState' class member 'cur' and local variable
'cursor') both played the role of YYCURSOR: YYCURSOR was defined to
'cursor', but the code had to adjust 'cur' to 'cursor' on every return
and restore it when reentering lexing procedures.

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

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

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

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

As it doesn't break any tests I hereby simply remove it.

9 years agoAdded tests for occasionally fixed bug in code generation.
Ulya Trofimovich [Wed, 12 Aug 2015 12:52:57 +0000 (13:52 +0100)]
Added tests for occasionally fixed bug in code generation.

The bug was triggered by the following conditions: '-b'
(or any flag that implies '-b') and encoding with code units
wider than 1 byte (that is, UTF-16, UTF-32 and UCS-2).

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

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

        Pass limited span instead of checking range all the time.

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

        - Allow to use -w with -b
        # Still quite some work to do but it is possible

9 years agoMore accurate loop counting (inspired by [-Wsign-compare]).
Ulya Trofimovich [Tue, 11 Aug 2015 17:52:41 +0000 (18:52 +0100)]
More accurate loop counting (inspired by [-Wsign-compare]).

9 years agoLoop counter should be unsigned (found with [-Wsign-compare]).
Ulya Trofimovich [Tue, 11 Aug 2015 16:44:29 +0000 (17:44 +0100)]
Loop counter should be unsigned (found with [-Wsign-compare]).

9 years agoSimplified regexp construction for case insensitive strings.
Ulya Trofimovich [Tue, 11 Aug 2015 16:36:29 +0000 (17:36 +0100)]
Simplified regexp construction for case insensitive strings.

As for now, we only support ASCII. This should be fixed.