├── examples ├── file.4 ├── hostmatch │ ├── error.canonical │ ├── good.canonical │ ├── hostmatch │ ├── bad.canonical │ └── source.in ├── file.3 ├── file.1 ├── file.2 ├── ircwatcher ├── fee ├── track-5.10 ├── unquotemeta ├── tld ├── roman ├── naive ├── failure.01.pl ├── stress-test.pl ├── debugging └── assemble ├── TODO ├── xt └── author │ ├── pod.t │ └── pod-coverage.t ├── .gitignore ├── .editorconfig ├── MANIFEST.SKIP ├── t ├── 10_perl514.t ├── 07_warning.t ├── 04_match.t ├── 08_track.t ├── 09_debug.t ├── 05_hostmatch.t ├── 01_insert.t └── 06_general.t ├── Makefile.PL ├── README ├── LICENSE ├── Changelog.ini └── Changes /examples/file.4: -------------------------------------------------------------------------------- 1 | cat/dog/cow/pig/hen -------------------------------------------------------------------------------- /examples/hostmatch/error.canonical: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/file.3: -------------------------------------------------------------------------------- 1 | en 2 | es 3 | il 4 | is 5 | -------------------------------------------------------------------------------- /examples/file.1: -------------------------------------------------------------------------------- 1 | sang 2 | sing 3 | song 4 | sung 5 | -------------------------------------------------------------------------------- /examples/file.2: -------------------------------------------------------------------------------- 1 | beat 2 | boat 3 | blot 4 | bleat 5 | -------------------------------------------------------------------------------- /examples/ircwatcher: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ronsavage/Regexp-Assemble/HEAD/examples/ircwatcher -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Fix Changes and Changelog.ini 2 | 3 | Andreas Konig => Andreas König 4 | David Rigaudiere => David Rigaudière 5 | -------------------------------------------------------------------------------- /xt/author/pod.t: -------------------------------------------------------------------------------- 1 | use Test::More; 2 | 3 | eval "use Test::Pod 1.45"; 4 | 5 | plan skip_all => "Test::Pod 1.45 required for testing POD" if $@; 6 | 7 | all_pod_files_ok(); 8 | -------------------------------------------------------------------------------- /xt/author/pod-coverage.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::Pod::Coverage 1.08; 5 | use Pod::Coverage::TrustPod; 6 | 7 | all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /blib/ 2 | /.build/ 3 | _build/ 4 | cover_db/ 5 | inc/ 6 | Build 7 | !Build/ 8 | Build.bat 9 | .last_cover_stats 10 | /Makefile 11 | /Makefile.old 12 | /MANIFEST 13 | /MANIFEST.bak 14 | /META.yml 15 | /META.json 16 | /MYMETA.* 17 | nytprof.out 18 | /pm_to_blib 19 | *.o 20 | *.bs 21 | /_eumm/ 22 | /Regexp-Assemble-* 23 | *.swp 24 | *~ 25 | ~* 26 | -------------------------------------------------------------------------------- /examples/fee: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl -w 2 | 3 | use strict; 4 | use Regexp::Assemble; 5 | 6 | my $re = Regexp::Assemble->new->add( qw[ fee fie foe fum ] ); 7 | 8 | while( ) { 9 | chomp; 10 | if( /($re)/ ) { 11 | print "Here be giants: $1\n"; 12 | } 13 | } 14 | 15 | print $re->as_string, "\n"; 16 | 17 | __DATA__ 18 | feedbag 19 | airfield 20 | foe 21 | fumble 22 | blorp 23 | -------------------------------------------------------------------------------- /examples/track-5.10: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl5.9.5 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use lib 'blib/lib'; 7 | use Regexp::Assemble; 8 | 9 | my $r = Regexp::Assemble->new->track(1)->add(qw(foo? bar{2} [Rr]at)); 10 | 11 | for my $w (qw(this food is rather barren)) { 12 | if ($w =~ /$r/) { 13 | print "$w matched by ", $r->source($^R), $/; 14 | } 15 | else { 16 | print "$w no match\n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/unquotemeta: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | # unquotemeta - how to fix up quotemeta 4 | # 5 | # part of the Regexp::Assemble module 6 | # David Landgren, copyright (c) 2005 7 | 8 | use strict; 9 | 10 | for my $ord( 0 .. 255 ) { 11 | my $ch = chr($ord); 12 | my $qm = quotemeta($ch); 13 | my $fix = fixup($qm); 14 | 15 | print "o=$ord c=$ch q=$qm f=$fix\n"; 16 | } 17 | 18 | sub fixup { 19 | my $ch = shift; 20 | $ch =~ s/^\\([^-\w$()*+.\/?@\[\\\]^{|}])$/$1/; 21 | $ch; 22 | } 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Explanation of this file: https://editorconfig.org 2 | # Style per 3 | # https://github.com/ronsavage/Regexp-Assemble/pull/8#issuecomment-605718707 4 | root = true 5 | 6 | [*] 7 | indent_style = tab 8 | indent_size = 4 9 | insert_final_newline = true 10 | 11 | # Test files with mixed indents: editor should not enforce indent style 12 | [t/{03_str.t,t/09_debug.t}] 13 | indent_style = unset 14 | 15 | # Input files with special formats 16 | [examples/file.4] 17 | insert_final_newline = false 18 | -------------------------------------------------------------------------------- /examples/tld: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl -w 2 | # 3 | # tld - generate a regular expression that matches the Internet 4 | # top level domains 5 | # 6 | # You can also specify an indent value to pretty-print the 7 | # resulting regexp. This example gives you a very good insight 8 | # as to how the alternations are sorted, busiest to least. 9 | # 10 | # Copyright (C) David Landgren 2005 11 | 12 | use strict; 13 | 14 | use Regexp::Assemble; 15 | 16 | my $indent = shift || 0; 17 | 18 | eval "use Net::Domain::TLD"; 19 | $@ and die "You must install Net::Domain::TLD to run this example\n"; 20 | 21 | my $re = Regexp::Assemble->new->add( Net::Domain::TLD->new->All ); 22 | 23 | print $re->as_string(indent => $indent), "\n"; 24 | -------------------------------------------------------------------------------- /examples/roman: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl -w 2 | # 3 | # roman - generate a regular expression that matches the roman numerals 4 | # from 1 to 20. 5 | # 6 | # you can over-ride the upper bound (20) by specifying the value 7 | # on the command line. You can also specify an indent value to 8 | # pretty-print the resulting regexp. 9 | # 10 | # Copyright (C) David Landgren 2005 11 | 12 | use strict; 13 | use Regexp::Assemble; 14 | 15 | my $max = shift || 20; 16 | my $indent = shift || 0; 17 | 18 | eval "use Math::Roman 'roman'"; 19 | $@ and die "You must install Math::Roman to run this example\n"; 20 | 21 | my $r = Regexp::Assemble->new; 22 | $r->add(roman($_)) for 1..$max; 23 | 24 | print $r->as_string( indent => $indent ), "\n"; 25 | -------------------------------------------------------------------------------- /MANIFEST.SKIP: -------------------------------------------------------------------------------- 1 | # Avoid version control files. 2 | ,v$ 3 | \B\.cvsignore$ 4 | \B\.git\b 5 | \B\.gitignore\b 6 | \B\.svn\b 7 | \bCVS\b 8 | \bRCS\b 9 | 10 | # Avoid Makemaker generated and utility files. 11 | \bblib 12 | \bblibdirs$ 13 | \bpm_to_blib$ 14 | \bMakefile$ 15 | \bMakeMaker-\d 16 | 17 | # Avoid Module::Build generated and utility files. 18 | \b_build 19 | \bBuild$ 20 | \bBuild.bat$ 21 | 22 | # Avoid Devel::Cover generated files 23 | \bcover_db 24 | 25 | # Avoid temp and backup files. 26 | ~$ 27 | \#$ 28 | \.# 29 | \.bak$ 30 | \.old$ 31 | \.rej$ 32 | \.tmp$ 33 | \.swp$ 34 | ^~ 35 | 36 | # Avoid OS-specific files/dirs 37 | # Mac OSX metadata 38 | \B\.DS_Store 39 | # Mac OSX SMB mount metadata files 40 | \B\._ 41 | 42 | # Avoid UltraEdit files. 43 | \.prj$ 44 | \.pui$ 45 | 46 | ^MYMETA.yml$ 47 | ^MYMETA\.json$ 48 | 49 | ^Regexp-Assemble-.* 50 | -------------------------------------------------------------------------------- /t/10_perl514.t: -------------------------------------------------------------------------------- 1 | # 10_perl514.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # Exercise regular expressions beyond perl 5.12 5 | # 6 | # copyright (C) 2011 David Landgren 7 | 8 | use strict; 9 | 10 | use Test::More; 11 | if ($] < 5.013) { 12 | plan skip_all => 'Irrelevant below perl <= 5.12'; 13 | } 14 | else { 15 | plan tests => 3; 16 | } 17 | 18 | 19 | use Regexp::Assemble; 20 | 21 | my $fixed = 'The scalar remains the same'; 22 | $_ = $fixed; 23 | 24 | { 25 | my $r = Regexp::Assemble->new->debug(8)->add(qw(this that)); 26 | my $re = $r->re; 27 | is( $re, '(?^:th(?:at|is))', 'time debug' ); 28 | } 29 | 30 | { 31 | my $r = Regexp::Assemble->new->add(qw(this that))->debug(8)->add('those'); 32 | my $re = $r->re; 33 | is( $re, '(?^:th(?:ose|at|is))', 'deferred time debug' ); 34 | } 35 | 36 | 37 | is( $_, $fixed, '$_ has not been altered' ); 38 | -------------------------------------------------------------------------------- /examples/hostmatch/good.canonical: -------------------------------------------------------------------------------- 1 | mail.merlin.atlantis.co.ac 2 | smtp4.sms.ac 3 | smtp7.sms.ac 4 | domail1.emirates.net.ae 5 | avas-mr09.fibertel.com.ar 6 | avas-mr10.fibertel.com.ar 7 | cumeil9.prima.com.ar 8 | mail.tisa-sistemas.com.ar 9 | cabel243b.bkf.at 10 | viefep11-int.chello.at 11 | viefep12-int.chello.at 12 | viefep15-int.chello.at 13 | viefep18-int.chello.at 14 | viefep19-int.chello.at 15 | static81-223-147-187.xdsl-line.inode.at 16 | 83-64-139-186.work.xdsl-line.inode.at 17 | chello213047128247.15.vie.surfer.at 18 | cust170.120.nw.tplus.at 19 | mail1.acnielsen.com.au 20 | mail.gtlaw.com.au 21 | orcus.its.uow.edu.au 22 | smtprelay.intellicentre.net.au 23 | 201.c.002.mel.iprimus.net.au 24 | smtp02.syd.iprimus.net.au 25 | s089c.static.pacific.net.au 26 | webmail3.onatel.bf 27 | aktor1.adeli.biz 28 | ns1.cheznous.biz 29 | w7.creditland.biz 30 | ns1.gazduire.biz 31 | mail2.hitechpros.biz 32 | relay.link2biz.biz 33 | mx2.wendhlp.biz 34 | mx2.wowie.biz 35 | mail2.comdominio.com.br 36 | pn41.neoline.com.br 37 | sv6.srnet.com.br 38 | cacheflow.sul.com.br 39 | itajuba.terra.com.br 40 | itaparica.terra.com.br 41 | itapoa.terra.com.br 42 | smtpout3.uol.com.br 43 | smtpout6.uol.com.br 44 | web6.vanet.com.br 45 | ricardo.adm.ita.cta.br 46 | -------------------------------------------------------------------------------- /Makefile.PL: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use ExtUtils::MakeMaker; 5 | 6 | eval "use ExtUtils::MakeMaker::Coverage"; 7 | 8 | if ( $@ ) 9 | { 10 | print "Skipping testcover target, ExtUtils::MakeMaker::Coverage not found\n"; 11 | } 12 | else 13 | { 14 | print "Adding testcover target\n"; 15 | } 16 | 17 | my(%params) = 18 | ( 19 | AUTHOR => 'David Landgren', 20 | ABSTRACT => 'Assemble multiple Regular Expressions into a single RE', 21 | clean => 22 | { 23 | FILES => 'cover_db blib/* Makefile MANIFEST Regexp-Assemble-*' 24 | }, 25 | dist => 26 | { 27 | COMPRESS => 'gzip', 28 | SUFFIX => 'gz' 29 | }, 30 | DISTNAME => 'Regexp-Assemble', 31 | NAME => 'Regexp::Assemble', 32 | PREREQ_PM => 33 | { 34 | 'constant' => 0, 35 | 'strict' => 0, 36 | 'vars' => 0, 37 | 'warnings' => 0, 38 | }, 39 | TEST_REQUIRES => 40 | { 41 | 'Test::More' => 1.001014, 42 | }, 43 | VERSION_FROM => 'lib/Regexp/Assemble.pm', 44 | ); 45 | 46 | if ( ($ExtUtils::MakeMaker::VERSION =~ /^\d\.\d\d$/) && ($ExtUtils::MakeMaker::VERSION > 6.30) ) 47 | { 48 | $params{LICENSE} = 'perl'; 49 | } 50 | 51 | if ($ExtUtils::MakeMaker::VERSION ge '6.46') 52 | { 53 | $params{META_MERGE} = 54 | { 55 | 'meta-spec' => 56 | { 57 | 'version' => 2, 58 | }, 59 | resources => 60 | { 61 | 'bugtracker' => 'https://rt.cpan.org/Public/Dist/Display.html?Name=Regexp-Assemble', 62 | repository => 63 | { 64 | 'type' => 'git', 65 | 'url' => 'https://github.com/ronsavage/Regexp-Assemble.git', 66 | 'web' => 'https://github.com/ronsavage/Regexp-Assemble', 67 | }, 68 | }, 69 | }; 70 | } 71 | 72 | WriteMakefile(%params); 73 | -------------------------------------------------------------------------------- /examples/naive: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl -w 2 | # 3 | # naive - generate a regular expression that will lex regular expressions 4 | # it is naive in the sense that it can't lex certain patterns, such as a 5 | # pattern that contains nested parentheses (e.g. /ab(?:cd(?ef)?gh)+ij/ ) 6 | # 7 | # The emitted regular expression is the default pattern that Regexp::Assemble 8 | # uses to pick apart a string into tokens suitable for being assembled. If it 9 | # isn't sufficiently sophisticated, you will have to supply your own lexer. 10 | # 11 | # Copyright (C) David Landgren 2004-2005 12 | 13 | use strict; 14 | 15 | my $directive = q{[bABCEGLQUXZ]}; 16 | 17 | my $punct = q{[^\\w]}; 18 | 19 | my $meta = q{[aefnrtdDwWsS]}; 20 | my $ctrl = q{c.}; 21 | my $octal = q{0\\d{2}}; 22 | my $hex = q{x(?:[\\da-fA-F]{2}|{[\\da-fA-F]{4}})}; 23 | my $named = q{N\\{\w+\\}}; 24 | my $prop = q{[Pp](?:\\{\w+\\}|.)}; 25 | 26 | my $single = q{[^\\w\\/{|}-]}; 27 | 28 | my $modifiable = qq{$punct|$meta|$ctrl|$octal|$hex|$named|$prop}; 29 | 30 | my $modifier = q{(?:[*+?]\\??|\\{\\d+(?:,\\d*)?\\}\\??)?}; 31 | 32 | my $backslash = qq{\\\\(?:$directive|[lu].|(?:$modifiable)$modifier)}; 33 | 34 | my $class = q{\\[.*?(?new(flags => 'i')->track(1); 8 | 9 | foreach my $reg ( 10 | '(?^ux: Coneheads(?^ux: [^\\p{Alnum}] )(?^ux: [^\\p{Alnum}] )(?^ux: [^\\p{Alnum}] )Dan(?^ux: [^\\p{Alnum}] )Aykroyd(?^ux: [^\\p{Alnum}] )Comedy(?^ux: [^\\p{Alnum}] )Eng )|(?^ux: Coneheads(?:[+]|%20)-(?:[+]|%20)Dan(?:[+]|%20)Aykroyd(?:[+]|%20)Comedy(?:[+]|%20)Eng)', 11 | # 'Coneheads(?^ux: [^\\p{Alnum}] )(?^ux: [^\\p{Alnum}] )(?^ux: [^\\p{Alnum}] )Dan(?^ux: [^\\p{Alnum}] )Aykroyd(?^ux: [^\\p{Alnum}] )Comedy(?^ux: [^\\p{Alnum}] )Eng', 12 | # 'Coneheads(?:[+]|%20)-(?:[+]|%20)Dan(?:[+]|%20)Aykroyd(?:[+]|%20)Comedy(?:[+]|%20)Eng', 13 | '(?^u:Coneheads\\ 1993)', 14 | ) { 15 | $re->add( $reg ); 16 | } 17 | 18 | foreach my $string ( 19 | "Coneheads - Dan Aykroyd Comedy Eng", 20 | "Coneheads+-+Dan+Aykroyd+Comedy+Eng", 21 | "Coneheads%20-%20Dan%20Aykroyd%20Comedy%20Eng", 22 | "Coneheads 1993", 23 | ) { 24 | if( $string =~ /$re/ ) { 25 | say "matched $string"; 26 | 27 | if( my $matched = $re->matched() ) { 28 | say "matched with: $matched"; 29 | } 30 | if( my $matched = $re->source($^R) ) { 31 | say "\$^R: $^R"; 32 | say "match source: $matched"; 33 | } 34 | 35 | say "work around: ", get_source($re, $string); 36 | } 37 | else { 38 | say "no match on $string"; 39 | say "get_source returns: ", get_source($re, $string); 40 | } 41 | say "-" x 70; 42 | } 43 | 44 | print Dumper $re; 45 | 46 | sub get_source { 47 | my ($re, $string) = @_; 48 | 49 | foreach my $r ( @{$re->{mlist}} ) { 50 | if( $string =~ /$r/ ) { 51 | return $r; 52 | } 53 | } 54 | return; 55 | } 56 | -------------------------------------------------------------------------------- /t/07_warning.t: -------------------------------------------------------------------------------- 1 | # 07_warning.t 2 | # 3 | # test suite for Regexp::Assemble 4 | # Make sure warnings are emitted when asked for 5 | # 6 | # copyright (C) 2005-2006 David Landgren 7 | 8 | use constant WARN_TESTS => 6; 9 | 10 | eval qq{use Test::More tests => WARN_TESTS}; 11 | if( $@ ) { 12 | warn "# Test::More not available, no tests performed\n"; 13 | print "1..1\nok 1\n"; 14 | exit 0; 15 | } 16 | 17 | my $have_Test_Warn; 18 | BEGIN { 19 | $have_Test_Warn = do { 20 | eval "use Test::Warn"; 21 | $@ ? 0 : 1; 22 | }; 23 | } 24 | 25 | use Regexp::Assemble; 26 | 27 | SKIP: { 28 | skip( 'Test::Warn not installed on this system', WARN_TESTS ) 29 | unless $have_Test_Warn; 30 | 31 | my $ra = Regexp::Assemble->new( dup_warn => 1 ) 32 | ->add( qw( abc def ghi )); 33 | 34 | my $rax = Regexp::Assemble->new( dup_warn => 0 ) 35 | ->add( qw( abc def ghi )); 36 | 37 | my $ram = Regexp::Assemble->new->dup_warn 38 | ->add( qw( abc def ghi )); 39 | 40 | warning_is { $rax->add( 'def' ) } { carped => "" }, "do not carp explicit"; 41 | 42 | SKIP: { 43 | skip( "Sub::Uplevel version $Sub::Uplevel::VERSION broken on 5.8.8, 0.13 or better required", 2 ) 44 | if $] == 5.008008 and $Sub::Uplevel::VERSION < 0.13; 45 | 46 | warning_like { $ra->add('def') } qr(duplicate pattern added: /def/ at \S+ line \d+\s*), 47 | "carp duplicate pattern, warn from new"; 48 | 49 | warning_like { $ram->add('abc') } qr(duplicate pattern added: /abc/ at \S+ line \d+\s*), 50 | "carp duplicate pattern, warn from method"; 51 | } 52 | 53 | $ra->dup_warn(0); 54 | warning_is { $ra->add( 'ghi' ) } { carped => "" }, "do not carp"; 55 | $ra->dup_warn(1); 56 | 57 | my $dup_count = 0; 58 | $ra->dup_warn( sub { ++$dup_count } ); 59 | $ra->add( 'abc' ); 60 | cmp_ok( $dup_count, 'eq', 1, 'dup callback' ); 61 | 62 | $ra->dup_warn( 63 | sub { 64 | warn join('-', @{$_[-1]}) 65 | } 66 | ); 67 | $ra->add( 'dup' ); 68 | warning_is { $ra->add( 'dup' ) } 'd-u-p', 69 | "custom carp duplicate pattern"; 70 | 71 | } # SKIP 72 | -------------------------------------------------------------------------------- /examples/stress-test.pl: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl -w 2 | 3 | use strict; 4 | use lib 'blib/lib'; 5 | use Regexp::Assemble; 6 | use Data::PowerSet; 7 | use Algorithm::Combinatorics 'combinations'; 8 | 9 | my $end = shift || 'e'; # generate the power set of the elements 'a' .. $end 10 | 11 | my $set = [sort {join('' => @$a) cmp join('' => @$b)} 12 | @{Data::PowerSet::powerset( {min=>1}, 'a'..$end )} 13 | ]; 14 | 15 | $| = 1; 16 | 17 | print "## size of powerset = ", scalar(@$set), "\n"; 18 | 19 | my $nr = 0; 20 | for my $sel (@ARGV) { 21 | my $p = combinations($set,$sel); 22 | 23 | while (defined(my $s = $p->next)) { 24 | ++$nr; 25 | my $short = Regexp::Assemble->new; 26 | $short->insert(@$_) for @$s; 27 | my $long = Regexp::Assemble->new; 28 | $long->insert('^', @$_, '$') for @$s; 29 | my $sh = $short->as_string; 30 | my $lg = $long->as_string; 31 | 32 | $s = [map {join '' => @$_} @$s]; 33 | printf "%9d %2d %s $lg\n", $nr, $sel, "@$s" unless $nr % 10000; 34 | 35 | my %expected = map{($_,$_)} @$s; 36 | if( "^$sh\$" ne $lg ) { 37 | $lg =~ s/^\^//; 38 | $lg =~ s/\$$//; 39 | 40 | for my $t ( @$s) { 41 | if( $expected{$t} ) { 42 | next if $t =~ /$long/; 43 | printf "%5d %-50s %s\n", $nr, $lg, "@$s"; 44 | print "l: $t should have been matched\n"; 45 | last; 46 | } 47 | else { 48 | next if $t !~ /$long/; 49 | printf "%5d %-50s %s\n", $nr, $lg, "@$s"; 50 | print "l: $t should not have been matched\n"; 51 | last; 52 | } 53 | } 54 | 55 | my $short_str = '^' . $sh . '$'; 56 | my $short_re = qr/$short_str/; 57 | for my $t ( @$s) { 58 | if( $expected{$t} ) { 59 | next if $t =~ /$short_re/; 60 | printf "%5d %-50s %s\n", $nr, $sh, "@$s"; 61 | print "s: $t should have been matched\n"; 62 | last; 63 | } 64 | else { 65 | next if $t !~ /$short_re/; 66 | printf "%5d %-50s %s\n", $nr, $sh, "@$s"; 67 | print "s: $t should not have been matched\n"; 68 | last; 69 | } 70 | } 71 | 72 | } 73 | else { 74 | for my $t ( @$s) { 75 | if( $expected{$t} ) { 76 | next if $t =~ /$long/; 77 | printf "%5d %-50s %s\n", $nr, $lg, "@$s"; 78 | print "$t should have been matched\n"; 79 | last; 80 | } 81 | else { 82 | next if $t !~ /$long/; 83 | printf "%5d %-50s %s\n", $nr, $sh, "@$s"; 84 | print "$t should not have been matched\n"; 85 | last; 86 | } 87 | } 88 | } 89 | } 90 | print "# $sel $nr\n"; 91 | } 92 | 93 | print "$nr combinations examined\n"; 94 | -------------------------------------------------------------------------------- /examples/debugging: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl -w 2 | # 3 | # debugging - strategies for dealing with assembled patterns that 4 | # cannot be compiled. Usual message is 5 | # "Unmatched ( in regex; marked by <-- HERE in m/a( <-- HERE" 6 | # 7 | # Copyright (C) David Landgren 2005 8 | 9 | use strict; 10 | use Getopt::Std; 11 | use Regexp::Assemble; 12 | 13 | use vars '$VERSION'; 14 | $VERSION = '0.1'; 15 | 16 | getopts( 'v', \my %opt ); 17 | 18 | print "$VERSION\n" and exit if $opt{v}; 19 | 20 | my $r = Regexp::Assemble->new; 21 | 22 | while( <> ) { 23 | chomp; 24 | 25 | # take a copy of the assembly and add the next pattern 26 | my $clone = $r->clone; 27 | $clone->add($_); 28 | 29 | # if we compile the regexp, does it blow up? 30 | eval { my $regexp = $clone->re }; 31 | 32 | # it blew up 33 | if( $@ ) { 34 | report(); 35 | } 36 | else { 37 | # ok, now add it for real to the assembly 38 | $r->add( $_ ); 39 | } 40 | } 41 | 42 | sub report { 43 | my $lsqb = $_ =~ tr/[/[/; 44 | my $rsqb = $_ =~ tr/]/]/; 45 | my $lpar = $_ =~ tr/(/(/; 46 | my $rpar = $_ =~ tr/)/)/; 47 | 48 | warn < file-of-patterns 66 | 67 | =head1 OPTIONS 68 | 69 | =over 5 70 | 71 | =item B<-v> 72 | 73 | prints out the version of script. 74 | 75 | =back 76 | 77 | =head1 DESCRIPTION 78 | 79 | By default, C uses a naive strategy for chopping 80 | up input. It can get upset if you try to feed it a pattern with 81 | nested parentheses. For instance, C and C will 82 | cause it to fail. If you really want to do that, you'll have to 83 | come up with a regexp that can chop the above into C, C<(b(c))> 84 | and C, C<(b(d))>. 85 | 86 | Of course, that will only buy you C at the 87 | present time. Teaching it to produce C would be 88 | considerably more complex. Patches welcome. 89 | 90 | So, when adding hundreds of patterns, it's not always obvious 91 | figuring out a way of isolating the offending pattern, especially 92 | when they are coming out of a file or some other process you don't 93 | have control over. 94 | 95 | The trick, then, consists of adding a pattern one at a time, and 96 | then standing back and watching whether producing a regexp from the 97 | list of patterns seen so far will cause things to blow up. So you 98 | take a copy of the assembly, and add the pattern to the copy. If 99 | that works, then add it to the real assembly. Repeat until done. 100 | 101 | You don't want to do this all the time, because it is of course 102 | much less efficient. 103 | 104 | =head1 SEE ALSO 105 | 106 | L 107 | 108 | =head1 AUTHOR 109 | 110 | Copyright (C) 2005 David Landgren. All rights reserved. 111 | 112 | =head1 LICENSE 113 | 114 | This script is free software; you can redistribute it and/or modify it 115 | under the same terms as Perl itself. 116 | -------------------------------------------------------------------------------- /examples/assemble: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl -w 2 | # 3 | # assemble - read lines from STDIN and assemble them into a pattern 4 | # 5 | # Copyright (C) David Landgren 2004-2008 6 | 7 | use strict; 8 | use Getopt::Std; 9 | use Regexp::Assemble; 10 | 11 | use Time::HiRes 'time'; 12 | 13 | use vars '$VERSION'; 14 | $VERSION = '0.92'; 15 | 16 | getopts( 'abcd:f:i:nprsSt:TuUvw', \my %opt ); 17 | 18 | print "$VERSION\n" and exit if $opt{v}; 19 | 20 | $opt{d} |= 8 if $opt{T}; 21 | 22 | my $ra = Regexp::Assemble->new( 23 | chomp => 1, 24 | debug => $opt{d} || 0, 25 | fold_meta_pairs => exists $opt{f} ? 0 : 1, 26 | reduce => exists $opt{r} ? 0 : 1, 27 | dup_warn => exists $opt{u} ? 1 : 0, 28 | lookahead => exists $opt{a} ? 1 : 0, 29 | unroll_plus => exists $opt{U} ? 1 : 0, 30 | ); 31 | 32 | if( $opt{b} or $opt{c} ) { 33 | if( !$opt{b} ) { 34 | # filter comments 35 | $ra->pre_filter( sub { $_[0] =~ s/\s*#.*$//; 1 } ); 36 | } 37 | elsif( !$opt{c} ) { 38 | # filter blank lines 39 | $ra->pre_filter( sub { length(shift) } ); 40 | } 41 | else { 42 | # filter comments and blank lines. 43 | # (removing a comment may can cause a line to become blank 44 | $ra->pre_filter( sub { 45 | $_[0] =~ s/\s*#.*$//; 46 | length($_[0]) 47 | } ); 48 | } 49 | } 50 | 51 | $ra->add( <> ); 52 | 53 | # need to tickle reduction explicitly in the event of -S and -d8 54 | $ra->_reduce() if $opt{S} and $opt{d} and ($opt{d} & 8); 55 | 56 | if( $opt{i} or $opt{p} or not ($opt{t} or $opt{S}) ) { 57 | print $ra->as_string( indent => $opt{i} || 0 ); 58 | print "\n" unless $opt{n}; 59 | } 60 | 61 | if( $opt{s} or $opt{S} ) { 62 | warn qq{# nr=@{[$ra->stats_add]} dup=@{[$ra->stats_dup]} raw=@{[$ra->stats_raw]} cooked=@{[$ra->stats_cooked]} len=@{[$ra->stats_length]}\n}; 63 | } 64 | 65 | if( $opt{t} ) { 66 | my $error = 0; 67 | my $file = $opt{t}; 68 | open IN, $file or die "Cannot open $file for input: $!\n"; 69 | print $ra->as_string, "\n"; 70 | while( ) { 71 | chomp; 72 | if( $opt{w} ) { 73 | next if $_ =~ /^$ra$/; 74 | } 75 | else { 76 | next if $_ =~ /$ra/; 77 | } 78 | print "FAIL <$_>\n"; 79 | ++$error; 80 | } 81 | close IN; 82 | exit($error ? 1 : 0); 83 | } 84 | 85 | =head1 NAME 86 | 87 | assemble - Assemble a list of regular expressions from a file 88 | 89 | =head1 SYNOPSIS 90 | 91 | assemble -abcdfinprsStTuUvw file [...] 92 | 93 | =head1 DESCRIPTION 94 | 95 | Assemble a list of regular expression either from standard input or a 96 | file, using the Regexp::Assemble module. 97 | 98 | =head1 OPTIONS 99 | 100 | =over 5 101 | 102 | =item B<-a> 103 | 104 | look Ahead. Insert C<(?=...)> zero-width lookahead assertions in the pattern, 105 | where necessary. 106 | 107 | =item B<-b> 108 | 109 | Blank. Ignore blank lines. 110 | 111 | =item B<-c> 112 | 113 | Comment. Basic comment filtering. Strip off perl/shell comments (C<\s*#.*$/>). 114 | 115 | =item B<-d> 116 | 117 | Debug. Turns on debugging output. See L for suitable values. 118 | 119 | =item B<-i> 120 | 121 | Indent. Print the regular expression using and indent of n to display 122 | nesting. A.k.a pretty-printing. Implies -p. 123 | 124 | =item B<-n> 125 | 126 | No newline. Do not print a newline after the pattern. Useful when 127 | interpolating the output into a templating system or similar. 128 | 129 | =item B<-p> 130 | 131 | Print. Print the pattern. This is the default, however, it is 132 | required when the -t switch is enabled (because if you want to test 133 | patterns ordinarily you don't care what the the assembled pattern 134 | looks like). 135 | 136 | =item B<-r> 137 | 138 | Reduce. The default behaviour is to reduce the assembled pattern. 139 | Enabling this switch causes the reduction algorithm to be switched 140 | off. This can help you determine how much reduction is performed. 141 | 142 | assemble pattern.file | wc 143 | # versus 144 | assemble -r pattern.file | wc 145 | 146 | =item B<-s> 147 | 148 | Statistics. Print some statistics about the assembled pattern. The 149 | output is sent to STDERR (in order to allow the generated pattern 150 | to be redirected elsewhere). 151 | 152 | =item B<-S> 153 | 154 | Statistics only. Like B<-s>, except that the pattern itself is not 155 | output. Useful with B<-d 8> to see the time taken. 156 | 157 | =item B<-t> 158 | 159 | Test. Test the assembled expression against the contents of a file. 160 | Each line is read from the file and is matched against the pattern. 161 | Lines that fail to match are printed. In other words, no output is 162 | good output. In this mode of operation, error status is 1 in the 163 | case of a failure, 0 if all lines matched. 164 | 165 | =item B<-T> 166 | 167 | Time. Print statistics on the time taken to reduce and assemble the 168 | pattern. (This is merely a lazy person's synonym for C<-d 8>). 169 | 170 | =item B<-u> 171 | 172 | Unique. Carp if duplicate patterns are found. 173 | 174 | =item B<-U> 175 | 176 | Unroll. Transform C I into C (which may 177 | allow additional reductions). 178 | 179 | =item B<-v> 180 | 181 | Version. Print the version of the assemble script. 182 | 183 | =item B<-w> 184 | 185 | Word/Whole. When testing the contents of a file with C<-t>, bracket 186 | the expression with C<^> and C<$> in order to match the whole word 187 | or line from the file. 188 | 189 | =back 190 | 191 | =head1 DIAGNOSTICS 192 | 193 | Will print out a summary of the problem if an added pattern causes 194 | the assembly to fail. 195 | 196 | =head1 SEE ALSO 197 | 198 | L 199 | 200 | =head1 AUTHOR 201 | 202 | Copyright (C) 2004-2008 David Landgren. All rights reserved. 203 | 204 | =head1 LICENSE 205 | 206 | This script is free software; you can redistribute it and/or modify it 207 | under the same terms as Perl itself. 208 | -------------------------------------------------------------------------------- /t/04_match.t: -------------------------------------------------------------------------------- 1 | # 04_match.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # Tests to see than an assembled regexp matches all that it is supposed to 5 | # 6 | # copyright (C) 2004-2006 David Landgren 7 | 8 | use strict; 9 | eval qq{ 10 | use Test::More tests => 1381; 11 | }; 12 | if( $@ ) { 13 | warn "# Test::More not available, no tests performed\n"; 14 | print "1..1\nok 1\n"; 15 | exit 0; 16 | } 17 | 18 | use Regexp::Assemble; 19 | 20 | my $fixed = 'The scalar remains the same'; 21 | $_ = $fixed; 22 | 23 | # Bug #17507 as noted by barbie 24 | # 25 | # There appears to be a problem with the substitute key on Windows, for 26 | # at least Perl 5.6.1, which causes this test script to terminate 27 | # immediately on encountering the character. 28 | my $subchr = 0x1a; 29 | my $win32_56x = ($^O eq 'MSWin32' && $] < 5.008) ? 1 : 0; 30 | diag("enabling defensive workaround for $] on $^O") if $win32_56x; 31 | 32 | { 33 | for my $outer ( 0 .. 15 ) { 34 | my $re = Regexp::Assemble->new->anchor_string->chomp(0); 35 | for my $inner ( 0 .. 15 ) { 36 | next if $win32_56x and $subchr == ($outer*16 + $inner); 37 | $re->add( quotemeta( chr( $outer*16 + $inner ))); 38 | } 39 | for my $inner ( 0 .. 15 ) { 40 | if( $win32_56x and $subchr == ($outer*16 + $inner)) { 41 | ok( 1, "faking $subchr for 5.6 on Win32" ); 42 | } 43 | else { 44 | my $ch = chr($outer*16 + $inner); 45 | like( $ch, qr/$re/, "run $ch ($outer:$inner) $re" ); 46 | } 47 | } 48 | } 49 | } 50 | 51 | for( 0 .. 255 ) { 52 | if( $win32_56x and $subchr == $_) { 53 | pass("Fake a single for 5.6 on Win32"); 54 | next; 55 | } 56 | my $ch = chr($_); 57 | my $qm = Regexp::Assemble->new(chomp=>0)->anchor_string->add(quotemeta($ch)); 58 | like( $ch, qr/$qm/, "quotemeta(chr($_))" ); 59 | } 60 | 61 | for( 0 .. 127 ) { 62 | if( $win32_56x and $subchr == $_) { 63 | pass( "Fake a hi for 5.6 on Win32"); 64 | pass( "Fake a lo for 5.6 on Win32"); 65 | next; 66 | } 67 | my $lo = chr($_); 68 | my $hi = chr($_+128); 69 | my $qm = Regexp::Assemble->new(chomp => 0, anchor_string => 1)->add( 70 | quotemeta($lo), 71 | quotemeta($hi), 72 | ); 73 | like( $lo, qr/$qm/, "$_: quotemeta($lo) lo" ); 74 | like( $hi, qr/$qm/, "$_: quotemeta($hi) hi" ); 75 | } 76 | 77 | sub match { 78 | my $re = Regexp::Assemble->new; 79 | my $rela = Regexp::Assemble->new->lookahead(1); 80 | my $tag = shift; 81 | $re->add(@_); 82 | $rela->add(@_); 83 | my $reind = $re->clone; 84 | $reind = $re->clone->flags('x')->re(indent => 3); 85 | my $rered = $re->clone->reduce(0); 86 | my $str; 87 | for $str (@_) { 88 | like( $str, qr/^$re$/, "-- $tag: $str" ) or diag( " fail $str\n# match by $re\n" ); 89 | like( $str, qr/^$rela$/, "LA $tag: $str" ) or diag( " fail $str\n# match by lookahead $rela\n" ); 90 | like( $str, qr/^$reind$/x, "IN $tag: $str" ) or diag( " fail $str\n# match by indented $reind\n" ); 91 | like( $str, qr/^$rered$/, "RD $tag: $str" ) or diag( " fail $str\n# match by non-reduced $rered\n" ); 92 | } 93 | } 94 | 95 | sub match_list { 96 | my $tag = shift; 97 | my $patt = shift; 98 | my $test = shift; 99 | my $re = Regexp::Assemble->new->add(@$patt); 100 | my $rela = Regexp::Assemble->new->lookahead(1)->add(@$patt); 101 | my $str; 102 | for $str (@$test) { 103 | ok( $str =~ /^$re$/, "re $tag: $str" ) or diag( "fail re $str\n# in $re\n" ); 104 | ok( $str =~ /^$rela$/, "rela $tag: $str" ) or diag( "fail rela $str\n# in $rela\n" ); 105 | } 106 | } 107 | 108 | { 109 | my $re = Regexp::Assemble->new( flags => 'i' ) 110 | ->add( '^fg' ) 111 | ->re; 112 | like( 'fgx', qr/$re/, 'fgx/i' ); 113 | like( 'Fgx', qr/$re/, 'Fgx/i' ); 114 | like( 'FGx', qr/$re/, 'FGx/i' ); 115 | like( 'fGx', qr/$re/, 'fGx/i' ); 116 | unlike( 'F', qr/$re/, 'F/i' ); 117 | } 118 | 119 | { 120 | my $re = Regexp::Assemble->new( flags => 'x' ) 121 | ->add( '^fish' ) 122 | ->add( '^flash' ) 123 | ->add( '^fetish' ) 124 | ->add( '^foolish' ) 125 | ->re( indent => 2 ); 126 | like( 'fish', qr/$re/, 'fish/x' ); 127 | like( 'flash', qr/$re/, 'flash/x' ); 128 | like( 'fetish', qr/$re/, 'fetish/x' ); 129 | like( 'foolish', qr/$re/, 'foolish/x' ); 130 | unlike( 'fetch', qr/$re/, 'fetch/x' ); 131 | } 132 | 133 | match_list( 'lookahead car.*', 134 | [qw[caret caress careful careless caring carion carry carried]], 135 | [qw[caret caress careful careless caring carion carry carried]], 136 | ); 137 | 138 | match_list( 'a.x', [qw[ abx adx a.x ]] , [qw[ aax abx acx azx a4x a%x a+x a?x ]] ); 139 | 140 | match_list( 'POSIX', [qw[ X[0[:alpha:]%] Y[1-4[:punct:]a-c] ]] , [qw(X0 X% Xa Xf Y1 Y; Y! yc)] ); 141 | 142 | match_list( 'c.z', [qw[ c^z c-z c5z cmz ]] , [qw[ c^z c-z c5z cmz ]] ); 143 | 144 | match_list( '\d, \D', [ 'b\\d', 'b\\D' ] , [qw[ b4 bX b% b. b? ]] ); 145 | 146 | match_list( 'abcd', 147 | [qw[ abc abcd ac acd b bc bcd bd]], 148 | [qw[ abc abcd ac acd b bc bcd bd]], 149 | ); 150 | 151 | match( 'foo', qw[ foo bar rat quux ]); 152 | 153 | match( '.[ar]it 1', qw[ bait brit frit gait grit tait wait writ ]); 154 | 155 | match( '.[ar]it 2', qw[ bait brit gait grit ]); 156 | 157 | match( '.[ar]it 3', qw[ bit bait brit gait grit ]); 158 | 159 | match( '.[ar]it 4', qw[ barit bait brit gait grit ]); 160 | 161 | match( 't.*ough', qw[ tough though trough through thorough ]); 162 | 163 | match( 'g.*it', qw[ gait git grapefruit grassquit grit guitguit ]); 164 | 165 | match( 'show.*ess', qw[ showeriness showerless showiness showless ]); 166 | 167 | match( 'd*', qw[ den-at dot-at den-pt dot-pt dx ]); 168 | 169 | match( 'd*', qw[ den-at dot-at den-pt dot-pt d-at d-pt dx ]); 170 | 171 | match( 'un*ed', qw[ unimped unimpeded unimpelled ]); 172 | 173 | match( '(un)?*(ing)?ing', qw[ 174 | sing swing sting sling 175 | singing swinging stinging slinging 176 | unsing unswing unsting unsling 177 | unsinging unswinging unstinging unslinging 178 | ]); 179 | 180 | match( 's.*at 1', qw[ sat sweat sailbat ]); 181 | 182 | match( 'm[eant]+', qw[ ma mae man mana manatee mane manent manna mannan mant 183 | manta mat mate matta matte me mean meant meat meet meeten men met meta 184 | metate mete ]); 185 | 186 | match( 'ti[aeinost]+', qw[ tiao tie tien tin tine tinea tinean tineine 187 | tininess tinnet tinniness tinosa tinstone tint tinta tintie tintiness 188 | tintist tisane tit titanate titania titanite titano tite titi titian 189 | titien tittie ]); 190 | 191 | is( $_, $fixed, '$_ has not been altered' ); 192 | -------------------------------------------------------------------------------- /examples/hostmatch/hostmatch: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/perl -w 2 | # 3 | # hostmatch -- determine whether a DNS hostname matches a regular expression 4 | # 5 | 6 | use strict; 7 | use Regexp::Assemble; 8 | 9 | my $ra = Regexp::Assemble->new(chomp=>1)->add( ); 10 | 11 | open GOOD, '>good.out' or die "Cannot open good.out for output: $!\n"; 12 | open BAD, '>bad.out' or die "Cannot open bad.out for output: $!\n"; 13 | 14 | my( $good, $bad ) = (0, 0); 15 | while( <> ) { 16 | chomp; 17 | if( /^$ra$/ ) { 18 | ++$bad; 19 | } 20 | else { 21 | print GOOD "$_\n"; 22 | ++$good; 23 | } 24 | } 25 | 26 | close GOOD; 27 | close BAD; 28 | 29 | print "$good good record(s), $bad bad record(s), $. total\n"; 30 | 31 | __DATA__ 32 | m\d+-\d+-\d+-\d+\.andorpac\.ad 33 | de\d+\.alshamil\.net\.ae 34 | \d+-\d+-\d+-\d+\.fibertel\.com\.ar 35 | ol\d+-\d+\.fibertel\.com\.ar 36 | host\d+\.\d+\.\d+\.\d+\.ifxnw\.com\.ar 37 | int-\d+-\d+-\d+-\d+\.movi\.com\.ar 38 | host-\d+\.\d+\.\d+\.\d+-ta\.adsl\.netizen\.com\.ar 39 | dsl-\d+-\d+-\d+-\d+\.users\.telpin\.com\.ar 40 | \d+-\d+-\d+-\d+\.bbt\.net\.ar 41 | \d+-\d+-\d+-\d+\.prima\.net\.ar 42 | \d+-\d+-\d+-\d+\.cab\.prima\.net\.ar 43 | \d+-\d+-\d+-\d+\.dsl\.prima\.net\.ar 44 | \d+-\d+-\d+-\d+\.dup\.prima\.net\.ar 45 | \d+-\d+-\d+-\d+\.dup\.prima\.net\.ar 46 | \d+-\d+-\d+-\d+\.wll\.prima\.net\.ar 47 | host\d+\.\d+-\d+-\d+\.telecom\.net\.ar 48 | chello\d+\.\d+\.sc-graz\.chello\.at 49 | \d+-\d+-\d+-\d+\.dynamic\.home\.xdsl-line\.inode\.at 50 | \d+-\d+-\d+-\d+\.paris-lodron\.xdsl-line\.inode\.at 51 | h\d+\.dyn\.cm\.kabsi\.at 52 | h\d+\.med\.cm\.kabsi\.at 53 | h\d+\.moe\.cm\.kabsi\.at 54 | cm\d+-\d+\.liwest\.at 55 | \d+-\d+-\d+-\d+\.pircher\.at 56 | \d+-\d+-\d+-\d+\.dyn\.salzburg-online\.at 57 | chello\d+\.\d+\.graz\.surfer\.at 58 | chello\d+\.\d+\.klafu\.surfer\.at 59 | chello\d+\.tirol\.surfer\.at 60 | chello\d+\.\d+\.\d+\.vie\.surfer\.at 61 | d\d+-\d+-\d+-\d+\.cust\.tele\d+\.at 62 | m\d+p\d+\.adsl\.highway\.telekom\.at 63 | n\d+p\d+\.adsl\.highway\.telekom\.at 64 | l\d+p\d+\.dipool\.highway\.telekom\.at 65 | chello\d+\.\d+\.\d+\.univie\.teleweb\.at 66 | chello\d+\.\d+\.\d+\.wu-wien\.teleweb\.at 67 | dsl-linz\d+-\d+-\d+\.utaonline\.at 68 | dialup-\d+\.syd\.ar\.com\.au 69 | dialup-\d+\.\d+\.\d+\.\d+\.acc\d+-ball-lis\.comindico\.com\.au 70 | dialup-\d+\.\d+\.\d+\.\d+\.acc\d+-mcmi-dwn\.comindico\.com\.au 71 | dsl-\d+\.\d+\.\d+\.\d+\.dsl\.comindico\.com\.au 72 | \d+-\d+-\d+-\d+\.netspeed\.com\.au 73 | blaax\d+-a\d+\.dialup\.optusnet\.com\.au 74 | chtax\d+-\d+\.dialup\.optusnet\.com\.au 75 | lonax\d+-b\d+\.dialup\.optusnet\.com\.au 76 | rohax\d+-\d+\.dialup\.optusnet\.com\.au 77 | wayax\d+-\d+\.dialup\.optusnet\.com\.au 78 | winax\d+-\d+\.dialup\.optusnet\.com\.au 79 | wooax\d+-b\d+\.dialup\.optusnet\.com\.au 80 | d\d+-\d+-\d+-\d+\.dsl\.nsw\.optusnet\.com\.au 81 | c\d+-\d+-\d+-\d+\.eburwd\d+\.vic\.optusnet\.com\.au 82 | c\d+-\d+-\d+-\d+\.lowrp\d+\.vic\.optusnet\.com\.au 83 | \d+\.fip-\d+\.permisdn\.ozemail\.com\.au 84 | \d+-\d+-\d+-\d+-bri-ts\d+-\d+\.tpgi\.com\.au 85 | \d+-\d+-\d+-\d+-vic-pppoe\.tpgi\.com\.au 86 | \d+-\d+-\d+-\d+\.tpgi\.com\.au 87 | dar-\d+k-\d+\.tpgi\.com\.au 88 | sou-ts\d+-\d+-\d+\.tpgi\.com\.au 89 | ains-\d+-\d+-\d+-\d+\.ains\.net\.au 90 | cpe-\d+-\d+-\d+-\d+\.nsw\.bigpond\.net\.au 91 | cpe-\d+-\d+-\d+-\d+\.qld\.bigpond\.net\.au 92 | cpe-\d+-\d+-\d+-\d+\.sa\.bigpond\.net\.au 93 | cpe-\d+-\d+-\d+-\d+\.vic\.bigpond\.net\.au 94 | cpe-\d+-\d+-\d+-\d+\.wa\.bigpond\.net\.au 95 | ppp-\d+\.cust\d+-\d+-\d+\.ghr\.chariot\.net\.au 96 | adsl-\d+\.cust\d+-\d+-\d+\.qld\.chariot\.net\.au 97 | \d+-\d+-\d+-\d+\.dyn\.iinet\.net\.au 98 | \d+\.a\.\d+\.mel\.iprimus\.net\.au 99 | \d+\.b\.\d+\.pth\.iprimus\.net\.au 100 | \d+\.a\.\d+\.sop\.iprimus\.net\.au 101 | r\d+-\d+-\d+-\d+\.cpe\.unwired\.net\.au 102 | dial-\d+\.\d+\.\d+\.\d+\.cotas\.com\.bo 103 | \d+-dial-user-ecp\.acessonet\.com\.br 104 | \d+-\d+-\d+-\d+\.corp\.ajato\.com\.br 105 | \d+\.\d+\.\d+\.\d+\.user\.ajato\.com\.br 106 | \d+-\d+-\d+-\d+\.user\.ajato\.com\.br 107 | \d+\.\d+\.\d+\.\d+\.user\.ajato\.com\.br 108 | cm-net-cwb-c[\da-f]+\.brdterra\.com\.br 109 | cm-net-poa-c[\da-f]+\.brdterra\.com\.br 110 | cm-tvcidade-rec-c[\da-f]+\.brdterra\.com\.br 111 | cm-tvcidade-ssa-c[\da-f]+\.brdterra\.com\.br 112 | cm-virtua-fln-c[\da-f]+\.brdterra\.com\.br 113 | cm-virtua-poa-c[\da-f]+\.brdterra\.com\.br 114 | net-\d+-\d+\.cable\.cpunet\.com\.br 115 | \d+-\d+-\d+\.xdsl-dinamico\.ctbcnetsuper\.com\.br 116 | \d+-\d+-\d+\.xdsl-fixo\.ctbcnetsuper\.com\.br 117 | dl-nas\d+-poa-c[\da-f]+\.dialterra\.com\.br 118 | \d+-\d+-\d+-\d+\.brt\.dialuol\.com\.br 119 | \d+-\d+-\d+-\d+\.tlf\.dialuol\.com\.br 120 | \d+-\d+-\d+-\d+\.tlm\.dialuol\.com\.br 121 | \d+-\d+-\d+-\d+\.rev\.easyband\.com\.br 122 | max-\d+-\d+-\d+\.nwnet\.com\.br 123 | \d+-\d+-\d+-\d+\.papalegua\.com\.br 124 | adsl\d+c\d+\.sercomtel\.com\.br 125 | \d+\.user\.veloxzone\.com\.br 126 | \d+\.virtua\.com\.br 127 | \d+\.bhz\.virtua\.com\.br 128 | [\da-f]+\.bhz\.virtua\.com\.br 129 | [\da-f]+\.rjo\.virtua\.com\.br 130 | [\da-f]+\.soc\.virtua\.com\.br 131 | [\da-f]+\.virtua\.com\.br 132 | \d+\.rjo\.virtua\.com\.br 133 | bhe\d+\.res-com\.wayinternet\.com\.br 134 | \d+-\d+-\d+-\d+\.mganm\d+\.dial\.brasiltelecom\.net\.br 135 | \d+-\d+-\d+-\d+\.pmjce\d+\.dial\.brasiltelecom\.net\.br 136 | \d+-\d+-\d+-\d+\.pnisir\d+\.dial\.brasiltelecom\.net\.br 137 | \d+-\d+-\d+-\d+\.pvoce\d+\.dial\.brasiltelecom\.net\.br 138 | \d+-\d+-\d+-\d+\.sance\d+\.dial\.brasiltelecom\.net\.br 139 | \d+-\d+-\d+-\d+\.bnut\d+\.dsl\.brasiltelecom\.net\.br 140 | \d+-\d+-\d+-\d+\.bsace\d+\.dsl\.brasiltelecom\.net\.br 141 | \d+-\d+-\d+-\d+\.cbabm\d+\.dsl\.brasiltelecom\.net\.br 142 | \d+-\d+-\d+-\d+\.cpece\d+\.dsl\.brasiltelecom\.net\.br 143 | \d+-\d+-\d+-\d+\.cslce\d+\.dsl\.brasiltelecom\.net\.br 144 | \d+-\d+-\d+-\d+\.ctame\d+\.dsl\.brasiltelecom\.net\.br 145 | \d+-\d+-\d+-\d+\.gnace\d+\.dsl\.brasiltelecom\.net\.br 146 | \d+-\d+-\d+-\d+\.jvece\d+\.dsl\.brasiltelecom\.net\.br 147 | \d+-\d+-\d+-\d+\.nhoce\d+\.dsl\.brasiltelecom\.net\.br 148 | \d+-\d+-\d+-\d+\.paemt\d+\.dsl\.brasiltelecom\.net\.br 149 | \d+-\d+-\d+-\d+\.pltce\d+\.dsl\.brasiltelecom\.net\.br 150 | \d+-\d+-\d+-\d+\.pvoce\d+\.dsl\.brasiltelecom\.net\.br 151 | \d+-\d+-\d+-\d+\.smace\d+\.dsl\.brasiltelecom\.net\.br 152 | \d+-\d+-\d+-\d+\.smace\d+\.e\.brasiltelecom\.net\.br 153 | \d+-\d+-\d+-\d+\.dialdata\.net\.br 154 | \d+\.\d+\.\d+\.\d+\.dialup\.gvt\.net\.br 155 | \d+\.\d+\.\d+\.\d+\.tbprof\.gvt\.net\.br 156 | \d+-\d+-\d+-\d+\.customer\.telesp\.net\.br 157 | \d+-\d+-\d+-\d+\.dial-up\.telesp\.net\.br 158 | \d+-\d+-\d+-\d+\.dsl\.telesp\.net\.br 159 | -------------------------------------------------------------------------------- /t/08_track.t: -------------------------------------------------------------------------------- 1 | # 08_track.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # Tests to see that tracked patterns behave themselves 5 | # 6 | # copyright (C) 2004-2007 David Landgren 7 | 8 | use strict; 9 | use constant TESTS => 75; 10 | 11 | eval qq{use Test::More tests => TESTS + 4}; 12 | if( $@ ) { 13 | warn "# Test::More not available, no tests performed\n"; 14 | print "1..1\nok 1\n"; 15 | exit 0; 16 | } 17 | 18 | my $PERL_VERSION_TOO_LOW = ($] < 5.007); 19 | my $PERL_VERSION_5_005 = ($] < 5.006); 20 | 21 | use Regexp::Assemble; 22 | 23 | my $fixed = 'The scalar remains the same'; 24 | $_ = $fixed; 25 | 26 | my $ra = Regexp::Assemble->new; 27 | 28 | is_deeply( $ra->mbegin, [], 'mbegin is [] on non-tracked R::A object' ); 29 | is_deeply( $ra->mend, [], 'mend is [] on non-tracked R::A object' ); 30 | 31 | { 32 | my $re = Regexp::Assemble->new 33 | ->add( 'cat' ) 34 | ->add( 'dog' ) 35 | ; 36 | my $regexp = $re->re; 37 | ok( $re->match( 'cat' ), 'match without tracking' ); 38 | ok( !defined( $re->match( 'eagle' )), 'match fail without tracking' ); 39 | } 40 | 41 | { 42 | my $re = Regexp::Assemble->new->track(1)->add(q(dog)); 43 | ok( $re->match('dog'), 're pattern-0 dog match' ); 44 | is( $re->source(0), 'dog', 'source is dog' ); 45 | 46 | $re = Regexp::Assemble->new( track=>1 ) 47 | ->add( qw/dog dogged fish fetish flash fresh/ ); 48 | $re->add('foolish-\\d+'); 49 | ok( $re->match('dog'), 're pattern-1 dog match' ); 50 | SKIP: { 51 | skip( "matched() is not implemented in this version of perl ($])", 1 ) if $PERL_VERSION_TOO_LOW; 52 | cmp_ok( $re->matched, 'eq', 'dog', 're pattern-1 dog matched' ); 53 | } 54 | ok( $re->match('dogged'), 're pattern-1 dogged match' ); 55 | SKIP: { 56 | skip( "matched() is not implemented in this version of perl ($])", 1 ) if $PERL_VERSION_TOO_LOW; 57 | cmp_ok( $re->matched, 'eq', 'dogged', 're pattern-1 dogged matched' ); 58 | } 59 | ok( $re->match('fetish'), 're pattern-1 fetish match' ); 60 | SKIP: { 61 | skip( "matched() is not implemented in this version of perl ($])", 1 ) if $PERL_VERSION_TOO_LOW; 62 | cmp_ok( $re->matched, 'eq', 'fetish', 're pattern-1 fetish matched' ); 63 | } 64 | ok( $re->match('foolish-245'), 're pattern-1 foolish-\\d+ match' ); 65 | SKIP: { 66 | skip( "matched() is not implemented in this version of perl ($])", 2 ) if $PERL_VERSION_TOO_LOW; 67 | cmp_ok( $re->matched, 'eq', 'foolish-\\d+', 're pattern-1 foolish-\\d+ matched' ); 68 | is ($re->source, 'foolish-\\d+', 're pattern-1 foolish source'); 69 | } 70 | ok( !defined($re->match('foolish-')), 're pattern-1 foolish-\\d+ 4' ); 71 | ok( !defined($re->source), 're pattern-1 foolish-\\d+ source' ); 72 | 73 | SKIP: { 74 | skip( "matched() is not implemented in this version of perl ($])", 1 ) if $PERL_VERSION_TOO_LOW; 75 | ok( !defined($re->matched), 're pattern-1 foolish-\\d+ 5' ); 76 | } 77 | if ($] < 5.009005) { 78 | ok( do {use re 'eval'; 'cat' !~ /$re/}, 're pattern-1 cat <5.10' ); 79 | ok( do {use re 'eval'; 'foolish-808' =~ /$re/}, 're pattern-1 foolish-808 <5.10' ); 80 | } 81 | else { 82 | ok( 'cat' !~ /$re/, 're pattern-1 cat 5.10' ); 83 | ok( 'foolish-808' =~ /$re/, 're pattern-1 foolish-808 5.10' ); 84 | } 85 | } 86 | 87 | { 88 | my $re = Regexp::Assemble->new( track=>1 ) 89 | ->add( '^a-\\d+$' ) 90 | ->add( '^a-\\d+-\\d+$' ); 91 | my $str = $re->as_string; 92 | SKIP: { 93 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 2 ) if $PERL_VERSION_5_005; 94 | ok( !defined $re->match('foo'), 'match pattern-2 foo' ); 95 | ok( defined($re->match('a-22-44')), 'match pattern-2 a-22-44' ); 96 | } 97 | SKIP: { 98 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 1 ) if $PERL_VERSION_5_005; 99 | cmp_ok( $re->match('a-22-55555'), 'eq', '^a-\\d+-\\d+$', 're pattern-2 a-22-55555' ); 100 | } 101 | SKIP: { 102 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 1 ) if $PERL_VERSION_5_005; 103 | ok( $re->match('a-000'), 're pattern-2 a-000 match' ); 104 | } 105 | SKIP: { 106 | skip( "matched() is not implemented in this version of perl ($])", 1 ) if $PERL_VERSION_TOO_LOW; 107 | cmp_ok( $re->matched, 'eq', '^a-\\d+$', 're pattern-2 a-000 matched' ); 108 | } 109 | } 110 | 111 | { 112 | my $re = Regexp::Assemble->new( track=>1 ) 113 | ->add( '^b-(\\d+)$' ) 114 | ->add( '^b-(\\d+)-(\\d+)$' ) 115 | ; 116 | SKIP: { 117 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 12 ) if $PERL_VERSION_5_005; 118 | ok( !defined $re->match('foo'), 'match pattern-3 foo' ); 119 | ok( defined $re->match('b-34-56'), 'match pattern-3 b-34-56' ); 120 | cmp_ok( $re->mvar(0), 'eq', 'b-34-56', 'match pattern-3 capture 1' ); 121 | cmp_ok( $re->mvar(1), '==', 34, 'match pattern-3 capture 2' ); 122 | cmp_ok( $re->mvar(2), '==', 56, 'match pattern-3 capture 3' ); 123 | is_deeply( $re->mvar, ['b-34-56', 34, 56], 'match pattern-3 mvar' ); 124 | is_deeply( $re->mbegin, [0, 2, 5], 'match pattern-3 mbegin' ); 125 | is_deeply( $re->mend, [7, 4, 7], 'match pattern-3 ' ); 126 | ok( defined $re->match('b-789'), 'match pattern-3 b-789' ); 127 | cmp_ok( $re->mvar(0), 'eq', 'b-789', 'match pattern-3 capture 4' ); 128 | cmp_ok( $re->mvar(1), '==', 789, 'match pattern-3 capture 5' ); 129 | ok( !defined($re->mvar(2)), 'match pattern-3 undef' ); 130 | } 131 | } 132 | 133 | { 134 | my $re = Regexp::Assemble->new( track=>1 ) 135 | ->add( '^c-(\\d+)$' ) 136 | ->add( '^c-(\\w+)$' ) 137 | ->add( '^c-([aeiou])-(\\d+)$' ) 138 | ; 139 | SKIP: { 140 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 12 ) if $PERL_VERSION_5_005; 141 | ok( !defined $re->match('foo'), 'match pattern-4 foo' ); 142 | ok( !defined $re->mvar(2), 'match pattern-4 foo novar' ); 143 | my $target = 'c-u-350'; 144 | ok( defined $re->match($target), "match pattern-4 $target" ); 145 | ok( $re->mvar(0) eq $target, 'match pattern-4 capture 1' ); 146 | ok( $re->mvar(1) eq 'u', 'match pattern-4 capture 2' ); 147 | ok( $re->mvar(2) == 350, 'match pattern-4 capture 3' ); 148 | $target = 'c-2048'; 149 | ok( defined $re->match($target), "match pattern-4 $target" ); 150 | ok( $re->mvar(0) eq $target, 'match pattern-4 capture 4' ); 151 | ok( $re->mvar(1) == 2048, 'match pattern-4 capture 5' ); 152 | ok( !defined($re->mvar(2)), 'match pattern-4 undef' ); 153 | is_deeply( $re->mbegin, [0, undef, undef, 2], 'match pattern-3 mbegin' ); 154 | is_deeply( $re->mend, [6, undef, undef, 6, undef], 'match pattern-3 mend' ); 155 | } 156 | } 157 | 158 | { 159 | my $re = Regexp::Assemble->new( track=>1 ) 160 | ->add( '^c-\\d+$' ) 161 | ->add( '^c-\\w+$' ) 162 | ->add( '^c-[aeiou]-\\d+$' ) 163 | ; 164 | SKIP: { 165 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 6 ) if $PERL_VERSION_5_005; 166 | ok( !defined $re->match('foo'), 'match pattern-5 foo' ); 167 | ok( !defined $re->mvar(2), 'match pattern-4 foo novar' ); 168 | my $target = 'c-u-350'; 169 | ok( defined $re->match($target), "match pattern-5 $target" ); 170 | ok( $re->mvar(0) eq $target, 'match pattern-5' ); 171 | ok( !defined $re->mvar(1), 'match pattern-5 no capture 2' ); 172 | ok( !defined $re->mvar(2), 'match pattern-5 no capture 3' ); 173 | } 174 | } 175 | 176 | { 177 | my $re = Regexp::Assemble->new( track=>1 ) 178 | ->add( '^cat' ) 179 | ->add( '^candle$' ) 180 | ->flags( 'i' ) 181 | ; 182 | SKIP: { 183 | skip( "match()/matched() return undef in this version of perl ($])", 8 ) if $PERL_VERSION_5_005; 184 | ok( !defined $re->match('foo'), 'not match pattern-6 foo' ); 185 | my $target = 'cat'; 186 | ok( defined $re->match($target), "match pattern-6 $target" ); 187 | cmp_ok( $re->matched, 'eq', '^cat', "match pattern-6 $target re" ); 188 | $target = 'CATFOOD'; 189 | ok( defined $re->match($target), "match pattern-6 $target" ); 190 | cmp_ok( $re->matched, 'eq', '^cat', "match pattern-6 $target re" ); 191 | $target = 'candle'; 192 | ok( defined $re->match($target), "match pattern-6 $target" ); 193 | cmp_ok( $re->matched, 'eq', '^candle$', "match pattern-6 $target re" ); 194 | $target = 'Candlestick'; 195 | ok( !defined $re->match($target), "match pattern-6 $target" ); 196 | } 197 | } 198 | 199 | { 200 | my @capture; 201 | my $re = Regexp::Assemble->new( track=>1 ) 202 | ->add( '^ab-(\d+)-(\d+)' ) 203 | ->add( '^ac-(\d+)' ) 204 | ->add( '^nothing' ) 205 | ->add( '^ad-((\d+)-(\d+))' ) 206 | ; 207 | SKIP: { 208 | skip( "/?{...}/ and \\d+ cause a panic in this version of perl ($])", 15 ) if $PERL_VERSION_5_005; 209 | ok( !defined($re->capture), 'match p7 no prior capture' ); 210 | 211 | ok( defined $re->match('nothing captured'), 'match p7-1' ); 212 | is( scalar($re->capture), 0, 'match p7-1 no capture' ); 213 | 214 | ok( defined $re->match('ac-417 captured'), 'match p7-2' ); 215 | @capture = $re->capture; 216 | is( scalar(@capture), 1, 'match p7-2 capture' ); 217 | is( $capture[0], 417, "match p7-2 value 0 ok" ); 218 | 219 | ok( defined $re->match('ab-21-17 captured'), 'match p7-3' ); 220 | @capture = $re->capture; 221 | is( scalar(@capture), 2, 'match p7-3 capture' ); 222 | is( $capture[0], 21, "match p7-3 value 0 ok" ); 223 | is( $capture[1], 17, "match p7-3 value 1 ok" ); 224 | 225 | ok( defined $re->match('ad-808-245 captured'), 'match p7-4' ); 226 | @capture = $re->capture; 227 | is( scalar(@capture), 3, 'match p7-4 capture' ); 228 | is( $capture[0], '808-245', "match p7-4 value 0 ok" ); 229 | is( $capture[1], 808, "match p7-4 value 1 ok" ); 230 | is( $capture[2], 245, "match p7-4 value 2 ok" ); 231 | } 232 | } 233 | 234 | cmp_ok( $_, 'eq', $fixed, '$_ has not been altered' ); 235 | -------------------------------------------------------------------------------- /t/09_debug.t: -------------------------------------------------------------------------------- 1 | # 09_debug.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # Exercise the debug parts 5 | # 6 | # copyright (C) 2006-2011 David Landgren 7 | 8 | use strict; 9 | 10 | eval qq{use Test::More tests => 68}; 11 | if( $@ ) { 12 | warn "# Test::More not available, no tests performed\n"; 13 | print "1..1\nok 1\n"; 14 | exit 0; 15 | } 16 | 17 | use Regexp::Assemble; 18 | 19 | my $PERL_VERSION_TOO_HIGH = ($] >= 5.013); 20 | 21 | my $fixed = 'The scalar remains the same'; 22 | $_ = $fixed; 23 | 24 | { 25 | my $r = Regexp::Assemble->new( debug => 15 ); 26 | is( $r->{debug}, 15, 'debug new(n)' ); 27 | $r->debug( 0 ); 28 | is( $r->{debug}, 0, 'debug(0)' ); 29 | $r->debug( 4 ); 30 | is( $r->{debug}, 4, 'debug(4)' ); 31 | $r->debug(); 32 | is( $r->{debug}, 0, 'debug()' ); 33 | } 34 | 35 | { 36 | my $u = Regexp::Assemble->new(unroll_plus => 1)->debug(4); 37 | my $str; 38 | 39 | $u->add( "[a]", ); 40 | $str = $u->as_string; 41 | is( $str, 'a', '[a] -> a' ); 42 | 43 | $u->add( "a+b", 'ac' ); 44 | $str = $u->as_string; 45 | is( $str, 'a(?:a*b|c)', 'unroll plus a+b ac' ); 46 | 47 | $u->add( "\\LA+B", "ac" ); 48 | $str = $u->as_string; 49 | is( $str, 'a(?:a*b|c)', 'unroll plus \\LA+B ac' ); 50 | 51 | $u->add( '\\Ua+?b', "AC" ); 52 | $str = $u->as_string; 53 | is( $str, 'A(?:A*?B|C)', 'unroll plus \\Ua+?b AC' ); 54 | 55 | $u->add( "\\d+d", "\\de" ); 56 | $str = $u->as_string; 57 | is( $str, '\\d(?:\d*d|e)', 'unroll plus \\d+d \\de' ); 58 | 59 | $u->add( "\\xab+f", "\\xabg" ); 60 | $str = $u->as_string; 61 | is( $str, "\xab(?:\xab*f|g)", 'unroll plus \\xab+f \\xabg' ); 62 | 63 | $u->add( "[a-e]+h", "[a-e]i" ); 64 | $str = $u->as_string; 65 | is( $str, "[a-e](?:[a-e]*h|i)", 'unroll plus [a-e]+h [a-e]i' ); 66 | 67 | $u->add( "a+b" ); 68 | $str = $u->as_string; 69 | is( $str, "a+b", 'reroll a+b' ); 70 | 71 | $u->add( "a+b", "a+" ); 72 | $str = $u->as_string; 73 | is( $str, "a+b?", 'reroll a+b?' ); 74 | 75 | $u->add( "a+?b", "a+?" ); 76 | $str = $u->as_string; 77 | is( $str, "a+?b?", 'reroll a+?b?' ); 78 | 79 | $u->add( qw(defused fused used) ); 80 | $str = $u->as_string; 81 | is( $str, "(?:(?:de)?f)?used", 'big debug block in _insert_path()' ); 82 | } 83 | 84 | { 85 | my $str = '\t+b*c?\\x41'; 86 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 87 | [ '\t+', 'b*', 'c?', 'A' ], 88 | "_lex $str", 89 | ); 90 | 91 | $str = '\Q['; 92 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 93 | [ '\\[' ], 94 | "_lex $str", 95 | ); 96 | 97 | $str = '\Q]'; 98 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 99 | [ '\\]' ], 100 | "_lex $str", 101 | ); 102 | 103 | $str = '\Q('; 104 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 105 | [ '\\(' ], 106 | "_lex $str", 107 | ); 108 | 109 | $str = '\Q)'; 110 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 111 | [ '\\)' ], 112 | "_lex $str", 113 | ); 114 | 115 | $str = '\Qa+b*c?'; 116 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 117 | [ 'a', '\+', 'b', '\*', 'c', '\?' ], 118 | "_lex $str", 119 | ); 120 | 121 | $str = 'a\\LBC\\Ude\\Ef\\Qg+'; 122 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), 123 | [ 'a', 'b', 'c', 'D', 'E', 'f', 'g', '\\+' ], 124 | "_lex $str", 125 | ); 126 | 127 | $str = 'a\\uC'; 128 | is_deeply( Regexp::Assemble->new(debug => 4) ->_lex( $str ), 129 | [ 'a', 'C' ], 130 | "_lex $str", 131 | ); 132 | 133 | $str = '\Q\/?'; 134 | is_deeply( Regexp::Assemble->new->debug(4)->_lex( $str ), [ '\/', '\?' ], "_lex $str" ); 135 | 136 | $str = 'p\\L\\QA+\\EZ'; 137 | is_deeply( Regexp::Assemble->new->debug(4)->add( $str )->_path, 138 | [ 'p', 'a', '\\+', 'Z' ], "add $str" ); 139 | 140 | $str = '^\Qa[b['; 141 | is_deeply( Regexp::Assemble->new->debug(15)->add( $str )->_path, 142 | [ '^', 'a', '\\[', 'b', '\\[' ], "add $str" ); 143 | } 144 | 145 | { 146 | my $r = Regexp::Assemble->new->debug(4)->add('\x45'); 147 | is_deeply( $r->_path, [ 'E' ], '_lex(\\x45) with debug' ); 148 | } 149 | 150 | { 151 | my $ra = Regexp::Assemble->new(debug => 1); 152 | $ra->insert( undef ); 153 | is_deeply( $ra->_path, [{'' => undef}], 'insert(undef)' ); 154 | } 155 | 156 | { 157 | my $r = Regexp::Assemble->new(lex => '\\d'); 158 | is_deeply( $r->debug(4)->add( '67abc123def+' )->_path, 159 | [ '6', '7', 'abc', '1', '2', '3', 'def+' ], 160 | '67abc123def+ with \\d lexer', 161 | ); 162 | is_deeply( $r->reset->debug(0)->add( '67ab12de+' )->_path, 163 | [ '6', '7', 'ab', '1', '2', 'de+' ], 164 | '67ab12de+ with \\d lexer', 165 | ); 166 | } 167 | 168 | { 169 | my $r = Regexp::Assemble->new(lex => '\\d'); 170 | is_deeply( $r->debug(4)->add( '67\\Q1a*\\E12jk' )->_path, 171 | [ '6', '7', '1', 'a', '\\*', '1', '2', 'jk' ], 172 | '67\\Q1a*\\E12jk with \\d lexer', 173 | ); 174 | } 175 | 176 | { 177 | my $r = Regexp::Assemble->new(lex => '\\d'); 178 | is_deeply( $r->debug(4)->add( '67\\Q1a*45k+' )->_path, 179 | [ '6', '7', '1', 'a', '\\*', '4', '5', 'k', '\\+' ], 180 | '67\\Q1a*45k+ with \\d lexer', 181 | ); 182 | } 183 | 184 | { 185 | my $r = Regexp::Assemble->new(lex => '\\d'); 186 | is_deeply( $r->debug(4)->add( '7\U6a' )->_path, 187 | [ '7', '6', 'A' ], 188 | '7\\U6a with \\d lexer', 189 | ); 190 | } 191 | 192 | { 193 | my $r = Regexp::Assemble->new(lex => '\\d'); 194 | is_deeply( $r->debug(4)->add( '8\L9C' )->_path, 195 | [ '8', '9', 'c' ], 196 | '8\\L9C with \\d lexer', 197 | ); 198 | } 199 | 200 | { 201 | my $r = Regexp::Assemble->new(lex => '\\d'); 202 | is_deeply( $r->debug(4)->add( '57\\Q2a+23d+' )->_path, 203 | [ '5', '7', '2', 'a', '\\+', '2', '3', 'd', '\\+' ], 204 | '57\\Q2a+23d+ with \\d lexer', 205 | ); 206 | } 207 | 208 | { 209 | my $save = $Regexp::Assemble::Default_Lexer; 210 | Regexp::Assemble::Default_Lexer('\\d'); 211 | my $r = Regexp::Assemble->new; 212 | is_deeply( $r->debug(4)->add( '67\\Uabc\\E123def' )->_path, 213 | [ '6', '7', '\\Uabc\\E', '1', '2', '3', 'def' ], 214 | '67\Uabc\\E123def with \\d lexer', 215 | ); 216 | 217 | is_deeply( $r->reset->add( '67\\Q(?:a)?\\E123def' )->_path, 218 | [ '6', '7', '\\Q(?:a)?\\E', '1', '2', '3', 'def' ], 219 | '67\Uabc\\E123def with \\d lexer', 220 | ); 221 | 222 | $Regexp::Assemble::Default_Lexer = $save; 223 | } 224 | 225 | is( Regexp::Assemble->new->debug(1)->add( qw/ 226 | 0\.0 0\.2 0\.7 0\.01 0\.003 227 | / )->as_string(indent => 4), 228 | '0\. 229 | (?: 230 | 0 231 | (?: 232 | 03 233 | |1 234 | ) 235 | ? 236 | |[27] 237 | )' 238 | , 'pretty 0.0 0.2 0.7 0.01 0.003' ); 239 | 240 | { 241 | my $ra = Regexp::Assemble->new->debug(3); 242 | 243 | is( $ra->add( qw/ dog darkness doggerel dark / )->as_string, 244 | 'd(?:ark(?:ness)?|og(?:gerel)?)' ); 245 | 246 | is( $ra->add( qw/ limit lit / )->as_string, 247 | 'l(?:im)?it' ); 248 | 249 | is( $ra->add( qw/ seafood seahorse sea / )->as_string, 250 | 'sea(?:horse|food)?' ); 251 | 252 | is( $ra->add( qw/ bird cat dog elephant fox / )->as_string, 253 | '(?:(?:elephan|ca)t|bird|dog|fox)' ); 254 | 255 | is( $ra->add( qw/ bit bat sit sat fit fat / )->as_string, 256 | '[bfs][ai]t' ); 257 | 258 | is( $ra->add( qw/ split splat slit slat flat flit / )->as_string, 259 | '(?:sp?|f)l[ai]t' ); 260 | 261 | is( $ra->add( qw/bcktx bckx bdix bdktx bdkx/ ) 262 | ->as_string, 'b(?:d(?:kt?|i)|ckt?)x', 263 | 'bcktx bckx bdix bdktx bdkx' ); 264 | 265 | is( $ra->add( qw/gait grit wait writ /)->as_string, 266 | '[gw][ar]it' ); 267 | 268 | is( $ra->add( qw/gait grit lit limit /)->as_string, 269 | '(?:l(?:im)?|g[ar])it' ); 270 | 271 | is( $ra->add( qw/bait brit frit gait grit tait wait writ /)->as_string, 272 | '(?:[bgw][ar]|fr|ta)it' ); 273 | 274 | is( $ra->add( qw/schoolkids acids acidoids/ )->as_string, 275 | '(?:ac(?:ido)?|schoolk)ids' ); 276 | 277 | is( $ra->add( qw/schoolkids acidoids/ )->as_string, 278 | '(?:schoolk|acido)ids' ); 279 | 280 | is( $ra->add( qw/nonschoolkids nonacidoids/ )->as_string, 281 | 'non(?:schoolk|acido)ids' ); 282 | 283 | is( $ra->add( qw/schoolkids skids acids acidoids/ )->as_string, 284 | '(?:s(?:chool)?k|ac(?:ido)?)ids' ); 285 | 286 | is( $ra->add( qw/kids schoolkids skids acids acidoids/ )->as_string, 287 | '(?:(?:s(?:chool)?)?k|ac(?:ido)?)ids' ); 288 | 289 | is( $ra->add( qw(abcd abd acd ad bcd bd d) )->as_string, 290 | '(?:(?:ab?|b)c?)?d', 'abcd abd acd ad bcd bd d', 291 | 'indentical nodes in sub_path/insert_node(bifurc)'); 292 | 293 | is( $ra->add( qw(^a$ ^ab$ ^abc$ ^abd$ ^bdef$ ^bdf$ ^bef$ ^bf$) )->as_string, 294 | '^(?:a(?:b[cd]?)?|bd?e?f)$', 'fused node'); 295 | 296 | is( $ra->add(qw[bait brit frit gait grit tait wait writ])->as_string, 297 | '(?:[bgw][ar]|fr|ta)it', 'after _insert_path()'); 298 | 299 | is( $ra->add(qw(0 1 10 100))->as_string, 300 | '(?:1(?:0?0)?|0)', '_scan_node slid' ); 301 | 302 | is( $ra->add( qw(abcd abd bcd bd d) )->as_string, 303 | '(?:a?bc?)?d', 'abcd abd bcd bd d' ); 304 | } 305 | 306 | SKIP: { 307 | skip("perl version too recent ($]), 5.012+ max", 2) if $PERL_VERSION_TOO_HIGH; 308 | { 309 | my $r = Regexp::Assemble->new->debug(8)->add(qw(this that)); 310 | my $re = $r->re; 311 | is( $re, '(?-xism:th(?:at|is))', 'time debug' ); 312 | } 313 | 314 | { 315 | my $r = Regexp::Assemble->new->add(qw(this that))->debug(8)->add('those'); 316 | my $re = $r->re; 317 | is( $re, '(?-xism:th(?:ose|at|is))', 'deferred time debug' ); 318 | } 319 | } 320 | 321 | { 322 | my $r = Regexp::Assemble->new->debug(8)->add(qw(this that those)); 323 | # sabotage 324 | delete $r->{_begin_time}; 325 | is( $r->as_string, 'th(?:ose|at|is)', 'time debug mangle' ); 326 | 327 | # use internal time() instead of Time::HiRes 328 | delete $r->{_time_func}; 329 | $r->{_use_time_hires} = 'more sabotage'; 330 | $r->reset->add(qw(abc ac)); 331 | is( $r->as_string, 'ab?c', 'internal time debug' ); 332 | } 333 | 334 | is_deeply( Regexp::Assemble->new->debug(4)->_fastlex('ab+c{2,4}'), 335 | ['a', 'b+', 'c{2,4}'], 336 | '_fastlex reg plus min-max' 337 | ); 338 | 339 | my $x; 340 | is_deeply( $x = Regexp::Assemble->new->debug(4)->_fastlex('\\d+\\s{3,4}?\\Qa+\\E\\lL\\uu\\Ufo\\E\\Lba\\x40'), 341 | ['\\d+', '\\s{3,4}?', 'a', '\\+', qw(l U F O b a @)], 342 | '_fastlex backslash' 343 | ) or diag("@$x"); 344 | 345 | is_deeply( Regexp::Assemble->new->debug(4)->_fastlex('\\Q\\L\\Ua+\\E\\Ub?\\Ec'), 346 | [qw(a \\+ B? c)], '_fastlex in and out of quotemeta' 347 | ); 348 | 349 | is_deeply( $x = Regexp::Assemble->new->debug(4)->_fastlex('\\bw[0-5]*\\\\(?:x|y){,5}?\\'), 350 | [qw(\\b w [0-5]* \\\\), '(?:x|y){,5}?'], '_fastlex more metachars' 351 | ) or diag("@$x"); 352 | 353 | is_deeply( $x = Regexp::Assemble->new(debug => 4)->_fastlex('\\cG\\007'), 354 | [qw(\\cG \\cG)], '_fastlex backslash misc' 355 | ) or diag("@$x"); 356 | 357 | is( $_, $fixed, '$_ has not been altered' ); 358 | -------------------------------------------------------------------------------- /t/05_hostmatch.t: -------------------------------------------------------------------------------- 1 | # 05_hostmatch.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # Test a mini-application that you can build with Regexp::Assemble 5 | # 6 | # copyright (C) 2004-2007 David Landgren 7 | 8 | use strict; 9 | use Regexp::Assemble; 10 | 11 | use constant file_testcount => 3; # tests requiring Test::File::Contents 12 | 13 | eval qq{use Test::More tests => 22 + file_testcount}; 14 | if( $@ ) { 15 | warn "# Test::More not available, no tests performed\n"; 16 | print "1..1\nok 1\n"; 17 | exit 0; 18 | } 19 | 20 | use constant NR_GOOD => 45; 21 | use constant NR_BAD => 529; 22 | use constant NR_ERROR => 0; 23 | 24 | my $fixed = 'The scalar remains the same'; 25 | $_ = $fixed; 26 | 27 | my $have_Test_File_Contents = do { 28 | eval { require Test::File::Contents; import Test::File::Contents }; 29 | $@ ? 0 : 1; 30 | }; 31 | 32 | my @re = ; 33 | 34 | # ordinarily we could have just chomp the array after having slurped 35 | # , but that would be no fun. 36 | 37 | # insert them all into an R::A object, chomping the lines 38 | my $ra = Regexp::Assemble->new->chomp(1)->add( @re ); 39 | 40 | is( ref($ra), 'Regexp::Assemble', 'have a Regexp::Assemble object' ); 41 | 42 | # now map each RE into its compiled form 43 | @re = map { chomp; qr/$_/ } @re; 44 | 45 | ok( open(GOOD, '>t/good.out'), "can open t/good.out for output" ) or print "# $!\n"; 46 | ok( open(BAD, '>t/bad.out'), "can open t/bad.out for output" ) or print "# $!\n"; 47 | ok( open(ERROR, '>t/error.out'), "can open t/error.out for output" ) or print "# $!\n"; 48 | 49 | my( $good, $bad, $error ) = (0, 0, 0); 50 | END { 51 | if( !$error ) { 52 | unlink $_ for qw{ t/good.out t/bad.out t/error.out }; 53 | } 54 | } 55 | 56 | ok( open(IN, 'examples/hostmatch/source.in'), "can open examples/hostmatch/source.in" ) or print "# $!\n"; 57 | while( defined( my $rec = )) { 58 | chomp $rec; 59 | if( $rec =~ /^$ra$/ ) { 60 | my $seen = 0; 61 | my $re; 62 | for $re (@re) { 63 | if( $rec =~ /^$re$/ ) { 64 | print BAD "$rec\n"; 65 | ++$bad; 66 | ++$seen; 67 | last; 68 | } 69 | } 70 | if( not $seen ) { 71 | print ERROR "$rec\n"; 72 | ++$error; 73 | } 74 | } 75 | else { 76 | my $seen = 0; 77 | my $re; 78 | for $re (@re) { 79 | if( $rec =~ /^$re$/ ) { 80 | print ERROR "$rec\n"; 81 | ++$error; 82 | ++$seen; 83 | last; 84 | } 85 | } 86 | if( not $seen ) { 87 | print GOOD "$rec\n"; 88 | ++$good; 89 | } 90 | } 91 | } 92 | 93 | close GOOD; 94 | close BAD; 95 | close ERROR; 96 | 97 | is( NR_GOOD, $good, NR_GOOD. ' good records not matched' ); 98 | is( NR_BAD, $bad, NR_BAD. ' bad records matched' ); 99 | is( NR_ERROR, $error, NR_ERROR. ' records in error' ); 100 | is( NR_GOOD+NR_BAD+NR_ERROR, $., "$. total records" ); 101 | 102 | SKIP: { 103 | skip( 'Test::File::Contents not installed on this system', file_testcount ) 104 | unless $have_Test_File_Contents; 105 | my $file; 106 | for $file( qw/good bad error/ ) { 107 | file_contents_identical( "t/$file.out", "examples/hostmatch/$file.canonical", "saw expected $file output" ); 108 | } 109 | } # SKIP 110 | 111 | { 112 | my $r = Regexp::Assemble->new; 113 | $r->add_file('examples/file.1')->add_file('examples/file.2'); 114 | is( $r->as_string, '(?:b(?:l(?:ea|o)|[eo]a)t|s[aiou]ng)', 115 | q{add_file('file.1'), add_file('file.2')}, 116 | 'add_file() 2 calls' 117 | ); 118 | 119 | is( 120 | Regexp::Assemble->new->chomp->add_file( qw[examples/file.1 examples/file.2] ) 121 | ->as_string, 122 | '(?:b(?:l(?:ea|o)|[eo]a)t|s[aiou]ng)', 123 | 'add_file() multiple files' 124 | ); 125 | 126 | is( 127 | Regexp::Assemble->new->chomp->add_file({ 128 | file => [qw[examples/file.1 examples/file.2]] 129 | }) 130 | ->as_string, 131 | '(?:b(?:l(?:ea|o)|[eo]a)t|s[aiou]ng)', 132 | 'add_file() alternate interface' 133 | ); 134 | 135 | my $str = Regexp::Assemble->new 136 | ->add_file({ file => ['examples/file.4'], rs => '/', }) 137 | ->as_string; 138 | is( $str, '(?:(?:do|pi)g|c(?:at|ow)|hen)', 139 | 'add_file with explicit record separator' 140 | ); 141 | 142 | is( Regexp::Assemble->new( rs => '/' ) 143 | ->add_file({ file => ['examples/file.4'] }) 144 | ->as_string, $str, 'add_file hashref with record separator specified in new()' 145 | ); 146 | 147 | is( Regexp::Assemble->new 148 | ->add_file({ file => 'examples/file.4', input_record_separator => '/', }) 149 | ->as_string, $str, 'add_file hashref with record separator specified in new()' 150 | ); 151 | 152 | is( Regexp::Assemble->new( rs => '/' ) 153 | ->add_file('examples/file.4') 154 | ->as_string, $str, 'add_file with record separator specified in new()' 155 | ); 156 | 157 | is( 158 | Regexp::Assemble->new( 159 | file => 'examples/file.4', 160 | input_record_separator => '/', 161 | ) 162 | ->as_string, $str, 163 | 'new() file and custom record separator' 164 | ); 165 | 166 | { 167 | local $/ = undef; 168 | my $raw_contents = 'cat/dog/cow/pig/hen'; 169 | 170 | is( Regexp::Assemble->new 171 | ->add_file({file => 'examples/file.4'}) 172 | ->as_string, $raw_contents, 'add_file with no record separator' 173 | ); 174 | 175 | is( 176 | Regexp::Assemble->new(file => 'examples/file.4')->as_string, 177 | $raw_contents, 178 | 'new() file and no record separator' 179 | ); 180 | } 181 | 182 | eval { my $r = Regexp::Assemble->new( file => '/does/not/exist' ) }; 183 | is( substr($@,0,38), q{cannot open /does/not/exist for input:}, 'file does not exist for new()' ); 184 | 185 | SKIP: { 186 | skip( 'ignore DOS line-ending tests on Win32', 1 ) if $^O =~ /^MSWin32/; 187 | is( 188 | Regexp::Assemble->new->chomp->add_file({ 189 | file => [qw[examples/file.3]], 190 | rs => "\r\n", 191 | }) 192 | ->as_string, 193 | '(?:e[ns]|i[ls])', 194 | 'add_file() with DOS line endings' 195 | ); 196 | } 197 | } 198 | 199 | is( $_, $fixed, '$_ has not been altered' ); 200 | 201 | __DATA__ 202 | m\d+-\d+-\d+-\d+\.andorpac\.ad 203 | de\d+\.alshamil\.net\.ae 204 | \d+-\d+-\d+-\d+\.fibertel\.com\.ar 205 | ol\d+-\d+\.fibertel\.com\.ar 206 | host\d+\.\d+\.\d+\.\d+\.ifxnw\.com\.ar 207 | int-\d+-\d+-\d+-\d+\.movi\.com\.ar 208 | host-\d+\.\d+\.\d+\.\d+-ta\.adsl\.netizen\.com\.ar 209 | dsl-\d+-\d+-\d+-\d+\.users\.telpin\.com\.ar 210 | \d+-\d+-\d+-\d+\.bbt\.net\.ar 211 | \d+-\d+-\d+-\d+\.prima\.net\.ar 212 | \d+-\d+-\d+-\d+\.cab\.prima\.net\.ar 213 | \d+-\d+-\d+-\d+\.dsl\.prima\.net\.ar 214 | \d+-\d+-\d+-\d+\.dup\.prima\.net\.ar 215 | \d+-\d+-\d+-\d+\.dup\.prima\.net\.ar 216 | \d+-\d+-\d+-\d+\.wll\.prima\.net\.ar 217 | host\d+\.\d+-\d+-\d+\.telecom\.net\.ar 218 | chello\d+\.\d+\.sc-graz\.chello\.at 219 | \d+-\d+-\d+-\d+\.dynamic\.home\.xdsl-line\.inode\.at 220 | \d+-\d+-\d+-\d+\.paris-lodron\.xdsl-line\.inode\.at 221 | h\d+\.dyn\.cm\.kabsi\.at 222 | h\d+\.med\.cm\.kabsi\.at 223 | h\d+\.moe\.cm\.kabsi\.at 224 | cm\d+-\d+\.liwest\.at 225 | \d+-\d+-\d+-\d+\.pircher\.at 226 | \d+-\d+-\d+-\d+\.dyn\.salzburg-online\.at 227 | chello\d+\.\d+\.graz\.surfer\.at 228 | chello\d+\.\d+\.klafu\.surfer\.at 229 | chello\d+\.tirol\.surfer\.at 230 | chello\d+\.\d+\.\d+\.vie\.surfer\.at 231 | d\d+-\d+-\d+-\d+\.cust\.tele\d+\.at 232 | m\d+p\d+\.adsl\.highway\.telekom\.at 233 | n\d+p\d+\.adsl\.highway\.telekom\.at 234 | l\d+p\d+\.dipool\.highway\.telekom\.at 235 | chello\d+\.\d+\.\d+\.univie\.teleweb\.at 236 | chello\d+\.\d+\.\d+\.wu-wien\.teleweb\.at 237 | dsl-linz\d+-\d+-\d+\.utaonline\.at 238 | dialup-\d+\.syd\.ar\.com\.au 239 | dialup-\d+\.\d+\.\d+\.\d+\.acc\d+-ball-lis\.comindico\.com\.au 240 | dialup-\d+\.\d+\.\d+\.\d+\.acc\d+-mcmi-dwn\.comindico\.com\.au 241 | dsl-\d+\.\d+\.\d+\.\d+\.dsl\.comindico\.com\.au 242 | \d+-\d+-\d+-\d+\.netspeed\.com\.au 243 | blaax\d+-a\d+\.dialup\.optusnet\.com\.au 244 | chtax\d+-\d+\.dialup\.optusnet\.com\.au 245 | lonax\d+-b\d+\.dialup\.optusnet\.com\.au 246 | rohax\d+-\d+\.dialup\.optusnet\.com\.au 247 | wayax\d+-\d+\.dialup\.optusnet\.com\.au 248 | winax\d+-\d+\.dialup\.optusnet\.com\.au 249 | wooax\d+-b\d+\.dialup\.optusnet\.com\.au 250 | d\d+-\d+-\d+-\d+\.dsl\.nsw\.optusnet\.com\.au 251 | c\d+-\d+-\d+-\d+\.eburwd\d+\.vic\.optusnet\.com\.au 252 | c\d+-\d+-\d+-\d+\.lowrp\d+\.vic\.optusnet\.com\.au 253 | \d+\.fip-\d+\.permisdn\.ozemail\.com\.au 254 | \d+-\d+-\d+-\d+-bri-ts\d+-\d+\.tpgi\.com\.au 255 | \d+-\d+-\d+-\d+-vic-pppoe\.tpgi\.com\.au 256 | \d+-\d+-\d+-\d+\.tpgi\.com\.au 257 | dar-\d+k-\d+\.tpgi\.com\.au 258 | sou-ts\d+-\d+-\d+\.tpgi\.com\.au 259 | ains-\d+-\d+-\d+-\d+\.ains\.net\.au 260 | cpe-\d+-\d+-\d+-\d+\.nsw\.bigpond\.net\.au 261 | cpe-\d+-\d+-\d+-\d+\.qld\.bigpond\.net\.au 262 | cpe-\d+-\d+-\d+-\d+\.sa\.bigpond\.net\.au 263 | cpe-\d+-\d+-\d+-\d+\.vic\.bigpond\.net\.au 264 | cpe-\d+-\d+-\d+-\d+\.wa\.bigpond\.net\.au 265 | ppp-\d+\.cust\d+-\d+-\d+\.ghr\.chariot\.net\.au 266 | adsl-\d+\.cust\d+-\d+-\d+\.qld\.chariot\.net\.au 267 | \d+-\d+-\d+-\d+\.dyn\.iinet\.net\.au 268 | \d+\.a\.\d+\.mel\.iprimus\.net\.au 269 | \d+\.b\.\d+\.pth\.iprimus\.net\.au 270 | \d+\.a\.\d+\.sop\.iprimus\.net\.au 271 | r\d+-\d+-\d+-\d+\.cpe\.unwired\.net\.au 272 | dial-\d+\.\d+\.\d+\.\d+\.cotas\.com\.bo 273 | \d+-dial-user-ecp\.acessonet\.com\.br 274 | \d+-\d+-\d+-\d+\.corp\.ajato\.com\.br 275 | \d+\.\d+\.\d+\.\d+\.user\.ajato\.com\.br 276 | \d+-\d+-\d+-\d+\.user\.ajato\.com\.br 277 | \d+\.\d+\.\d+\.\d+\.user\.ajato\.com\.br 278 | cm-net-cwb-c[\da-f]+\.brdterra\.com\.br 279 | cm-net-poa-c[\da-f]+\.brdterra\.com\.br 280 | cm-tvcidade-rec-c[\da-f]+\.brdterra\.com\.br 281 | cm-tvcidade-ssa-c[\da-f]+\.brdterra\.com\.br 282 | cm-virtua-fln-c[\da-f]+\.brdterra\.com\.br 283 | cm-virtua-poa-c[\da-f]+\.brdterra\.com\.br 284 | net-\d+-\d+\.cable\.cpunet\.com\.br 285 | \d+-\d+-\d+\.xdsl-dinamico\.ctbcnetsuper\.com\.br 286 | \d+-\d+-\d+\.xdsl-fixo\.ctbcnetsuper\.com\.br 287 | dl-nas\d+-poa-c[\da-f]+\.dialterra\.com\.br 288 | \d+-\d+-\d+-\d+\.brt\.dialuol\.com\.br 289 | \d+-\d+-\d+-\d+\.tlf\.dialuol\.com\.br 290 | \d+-\d+-\d+-\d+\.tlm\.dialuol\.com\.br 291 | \d+-\d+-\d+-\d+\.rev\.easyband\.com\.br 292 | max-\d+-\d+-\d+\.nwnet\.com\.br 293 | \d+-\d+-\d+-\d+\.papalegua\.com\.br 294 | adsl\d+c\d+\.sercomtel\.com\.br 295 | \d+\.user\.veloxzone\.com\.br 296 | \d+\.virtua\.com\.br 297 | \d+\.bhz\.virtua\.com\.br 298 | [\da-f]+\.bhz\.virtua\.com\.br 299 | [\da-f]+\.rjo\.virtua\.com\.br 300 | [\da-f]+\.soc\.virtua\.com\.br 301 | [\da-f]+\.virtua\.com\.br 302 | \d+\.rjo\.virtua\.com\.br 303 | bhe\d+\.res-com\.wayinternet\.com\.br 304 | \d+-\d+-\d+-\d+\.mganm\d+\.dial\.brasiltelecom\.net\.br 305 | \d+-\d+-\d+-\d+\.pmjce\d+\.dial\.brasiltelecom\.net\.br 306 | \d+-\d+-\d+-\d+\.pnisir\d+\.dial\.brasiltelecom\.net\.br 307 | \d+-\d+-\d+-\d+\.pvoce\d+\.dial\.brasiltelecom\.net\.br 308 | \d+-\d+-\d+-\d+\.sance\d+\.dial\.brasiltelecom\.net\.br 309 | \d+-\d+-\d+-\d+\.bnut\d+\.dsl\.brasiltelecom\.net\.br 310 | \d+-\d+-\d+-\d+\.bsace\d+\.dsl\.brasiltelecom\.net\.br 311 | \d+-\d+-\d+-\d+\.cbabm\d+\.dsl\.brasiltelecom\.net\.br 312 | \d+-\d+-\d+-\d+\.cpece\d+\.dsl\.brasiltelecom\.net\.br 313 | \d+-\d+-\d+-\d+\.cslce\d+\.dsl\.brasiltelecom\.net\.br 314 | \d+-\d+-\d+-\d+\.ctame\d+\.dsl\.brasiltelecom\.net\.br 315 | \d+-\d+-\d+-\d+\.gnace\d+\.dsl\.brasiltelecom\.net\.br 316 | \d+-\d+-\d+-\d+\.jvece\d+\.dsl\.brasiltelecom\.net\.br 317 | \d+-\d+-\d+-\d+\.nhoce\d+\.dsl\.brasiltelecom\.net\.br 318 | \d+-\d+-\d+-\d+\.paemt\d+\.dsl\.brasiltelecom\.net\.br 319 | \d+-\d+-\d+-\d+\.pltce\d+\.dsl\.brasiltelecom\.net\.br 320 | \d+-\d+-\d+-\d+\.pvoce\d+\.dsl\.brasiltelecom\.net\.br 321 | \d+-\d+-\d+-\d+\.smace\d+\.dsl\.brasiltelecom\.net\.br 322 | \d+-\d+-\d+-\d+\.smace\d+\.e\.brasiltelecom\.net\.br 323 | \d+-\d+-\d+-\d+\.dialdata\.net\.br 324 | \d+\.\d+\.\d+\.\d+\.dialup\.gvt\.net\.br 325 | \d+\.\d+\.\d+\.\d+\.tbprof\.gvt\.net\.br 326 | \d+-\d+-\d+-\d+\.customer\.telesp\.net\.br 327 | \d+-\d+-\d+-\d+\.dial-up\.telesp\.net\.br 328 | \d+-\d+-\d+-\d+\.dsl\.telesp\.net\.br 329 | -------------------------------------------------------------------------------- /t/01_insert.t: -------------------------------------------------------------------------------- 1 | # 01_insert.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # 5 | # When a series of paths are inserted in an R::A object, they are 6 | # stored into tree structure using a crafty blend of arrays and hashes. 7 | # 8 | # These tests verify that the tokens that are added to the 9 | # Regexp::Assemble object are stored correctly. 10 | # 11 | # The tests here verify to a much greater extent that the tree/hash structure 12 | # built up from repeated add() calls produce a structure that the 13 | # subsequent coalescing and reduction routines can operate upon correctly. 14 | # 15 | # copyright (C) 2004-2006 David Landgren 16 | 17 | use strict; 18 | use Regexp::Assemble; 19 | 20 | use constant permute_testcount => 120 * 5; # permute() has 120 (5!) variants 21 | 22 | eval qq{use Test::More tests => 50 + permute_testcount}; 23 | if( $@ ) { 24 | warn "# Test::More not available, no tests performed\n"; 25 | print "1..1\nok 1\n"; 26 | exit 0; 27 | } 28 | 29 | my $fixed = 'The scalar remains the same'; 30 | $_ = $fixed; 31 | 32 | { 33 | my $ra = Regexp::Assemble->new; 34 | $ra->insert( '' ); 35 | my $r = ($ra->_path)->[0]; 36 | is( ref($r), 'HASH', q{insert('') => first element is a HASH} ); 37 | is( scalar(keys %$r), 1, q{...and contains one key} ); 38 | ok( exists $r->{''}, q{...which is an empty string} ); 39 | ok( !defined($r->{''}), q{...and points to undef} ); 40 | } 41 | 42 | { 43 | my $ra = Regexp::Assemble->new; 44 | $ra->insert( 'a' ); 45 | my $r = $ra->_path; 46 | is( scalar @$r, 1, q{'a' => path of length 1} ); 47 | is( $r->[0], 'a', q{'a' => ...and is an 'a'} ); 48 | } 49 | 50 | { 51 | my $r = Regexp::Assemble->new; 52 | $r->insert(); 53 | $r->insert('a'); 54 | is_deeply( $r->_path, [{'' => undef, 'a' => ['a']}], q{insert(), insert('a')} ); 55 | } 56 | 57 | { 58 | my $ra = Regexp::Assemble->new; 59 | $ra->insert( 'a', 'b' ); 60 | my $r = $ra->_path; 61 | is( scalar @$r, 2, q{'ab' => path of length 2} ); 62 | is( join( '' => @$r ), 'ab', q{'ab' => ...and is 'a', 'b'} ); 63 | is( $ra->dump, '[a b]', 'dump([a b])' ); 64 | } 65 | 66 | { 67 | my $ra = Regexp::Assemble->new; 68 | $ra->insert( 'a', 'b' ); 69 | $ra->insert( 'a', 'c' ); 70 | is( $ra->dump, '[a {b=>[b] c=>[c]}]', 'dump([a {b c}])' ); 71 | my $r = $ra->_path; 72 | is( scalar @$r, 2, q{'ab,ac' => path of length 2} ); 73 | is( $r->[0], 'a', q{'ab,ac' => ...and first atom is 'a'} ); 74 | is( ref($r->[1]), 'HASH', q{'ab,ac' => ...and second is a node} ); 75 | $r = $r->[1]; 76 | is( scalar(keys %$r), 2, q{'ab,ac' => ...node has two keys} ); 77 | is( join( '' => sort keys %$r ), 'bc', 78 | q{'ab,ac' => ...keys are 'b','c'} ); 79 | ok( exists $r->{b}, q{'ab,ac' => ... key 'b' exists} ); 80 | is( ref($r->{b}), 'ARRAY', q{'ab,ac' => ... and points to a path} ); 81 | ok( exists $r->{c}, q{'ab,ac' => ... key 'c' exists} ); 82 | is( ref($r->{c}), 'ARRAY', q{'ab,ac' => ... and points to a path} ); 83 | } 84 | 85 | { 86 | my $ra = Regexp::Assemble->new; 87 | $ra->insert( undef ); 88 | is_deeply( $ra->_path, [{'' => undef}], 'insert(undef)' ); 89 | } 90 | 91 | { 92 | my $ra = Regexp::Assemble->new; 93 | $ra->insert( '' ); 94 | is_deeply( $ra->_path, [{'' => undef}], q{insert('')} ); 95 | } 96 | 97 | { 98 | my $r = Regexp::Assemble->new; 99 | $r->insert(); 100 | is_deeply( $r->_path, [{'' => undef}], 'insert()' ); 101 | } 102 | 103 | { 104 | my $ra = Regexp::Assemble->new; 105 | $ra->insert( '0' ); 106 | is_deeply( $ra->_path, 107 | [0], 108 | q{/0/}, 109 | ); 110 | } 111 | 112 | { 113 | my $ra = Regexp::Assemble->new; 114 | $ra->insert( qw/d/ ); 115 | is_deeply( $ra->_path, 116 | ['d'], 117 | '/d/', 118 | ); 119 | } 120 | 121 | { 122 | my $r = Regexp::Assemble->new->lex( '\([^(]*(?:\([^)]*\))?[^)]*\)|.' ); 123 | 124 | $r->reset->add( 'ab(cd)ef' ); 125 | is_deeply( $r->_path, 126 | [ 'a', 'b', '(cd)', 'e', 'f' ], 127 | 'ab(cd)ef (with parenthetical lexer)' 128 | ); 129 | 130 | $r->reset->add( 'ab(cd(ef)gh)ij' ); 131 | is_deeply( $r->_path, 132 | [ 'a', 'b', '(cd(ef)gh)', 'i', 'j' ], 133 | 'ab(cd(ef)gh)ij (with parenthetical lexer)' 134 | ); 135 | 136 | $r->reset->add( 'ab((ef)gh)ij' ); 137 | is_deeply( $r->_path, 138 | [ 'a', 'b', '((ef)gh)', 'i', 'j' ], 139 | 'ab((ef)gh)ij (with parenthetical lexer)' 140 | ); 141 | 142 | $r->reset->add( 'ab(cd(ef))ij' ); 143 | is_deeply( $r->_path, 144 | [ 'a', 'b', '(cd(ef))', 'i', 'j' ], 145 | 'ab(cd(ef))ij (with parenthetical lexer)' 146 | ); 147 | 148 | $r->reset->add( 'ab((ef))ij' ); 149 | is_deeply( $r->_path, 150 | [ 'a', 'b', '((ef))', 'i', 'j' ], 151 | 'ab((ef))ij (with parenthetical lexer)' 152 | ); 153 | } 154 | 155 | { 156 | my $r = Regexp::Assemble->new(lex => '\\d'); 157 | is_deeply( $r->add( '0\Q0C,+' )->_path, 158 | [ '0', '0', 'C', ',', '\\+' ], 159 | '0\\Q0C,+ with \\d lexer', 160 | ); 161 | } 162 | 163 | { 164 | my $ra = Regexp::Assemble->new; 165 | $ra->insert( qw/d a b/ ); 166 | is_deeply( $ra->_path, 167 | [qw/d a b/], 168 | '/dab/', 169 | ); 170 | } 171 | 172 | { 173 | my $ra = Regexp::Assemble->new; 174 | $ra->insert( qw/0 1/ ); 175 | $ra->insert( qw/0 2/ ); 176 | is_deeply( $ra->_path, 177 | [ 178 | '0', 179 | { 180 | '1' => ['1'], 181 | '2' => ['2'], 182 | }, 183 | ], 184 | '/01/ /02/', 185 | ); 186 | } 187 | 188 | { 189 | my $ra = Regexp::Assemble->new; 190 | $ra->insert( qw/0/ ); 191 | $ra->insert( qw/0 1/ ); 192 | $ra->insert( qw/0 2/ ); 193 | is_deeply( $ra->_path, 194 | [ 195 | '0', 196 | { 197 | '1' => ['1'], 198 | '2' => ['2'], 199 | '' => undef, 200 | }, 201 | ], 202 | '/0/ /01/ /02/', 203 | ); 204 | } 205 | 206 | { 207 | my $ra = Regexp::Assemble->new; 208 | $ra->insert( qw/d a m/ ); 209 | $ra->insert( qw/d a m/ ); 210 | is_deeply( $ra->_path, 211 | [ 212 | 'd', 'a', 'm', 213 | ], 214 | '/dam/ x 2', 215 | ); 216 | } 217 | 218 | { 219 | my $ra = Regexp::Assemble->new; 220 | $ra->insert( qw/d a y/ ); 221 | $ra->insert( qw/d a/ ); 222 | $ra->insert( qw/d a/ ); 223 | is_deeply( $ra->_path, 224 | [ 225 | 'd', 'a', 226 | { 227 | 'y' => ['y'], 228 | '' => undef, 229 | }, 230 | ], 231 | '/day/, /da/ x 2', 232 | ); 233 | } 234 | 235 | { 236 | my $ra = Regexp::Assemble->new; 237 | $ra->insert( qw/d o t/ ); 238 | $ra->insert( qw/d o/ ); 239 | $ra->insert( qw/d/ ); 240 | is_deeply( $ra->_path, 241 | [ 242 | 'd', 243 | { 244 | 'o' => [ 245 | 'o', 246 | { 247 | 't' => ['t'], 248 | '' => undef, 249 | }, 250 | ], 251 | '' => undef, 252 | }, 253 | ], 254 | '/dot/ /do/ /d/', 255 | ); 256 | } 257 | 258 | { 259 | my $ra = Regexp::Assemble->new; 260 | $ra->insert( qw/b i g/ ); 261 | $ra->insert( qw/b i d/ ); 262 | is_deeply( $ra->_path, 263 | [ 264 | 'b', 'i', 265 | { 266 | 'd' => ['d'], 267 | 'g' => ['g'], 268 | }, 269 | ], 270 | '/big/ /bid/', 271 | ); 272 | } 273 | 274 | { 275 | my $ra = Regexp::Assemble->new; 276 | $ra->insert( qw/d a r t/ ); 277 | $ra->insert( qw/d a m p/ ); 278 | is_deeply( $ra->_path, 279 | [ 280 | 'd', 'a', 281 | { 282 | 'r' => ['r', 't'], 283 | 'm' => ['m', 'p'], 284 | }, 285 | ], 286 | '/dart/ /damp/', 287 | ); 288 | } 289 | 290 | { 291 | my $ra = Regexp::Assemble->new; 292 | $ra->insert( qw/a m b l e/ ); 293 | $ra->insert( qw/i d l e/ ); 294 | is_deeply( $ra->_path, 295 | [ 296 | { 297 | 'a' => ['a', 'm', 'b', 'l', 'e'], 298 | 'i' => ['i', 'd', 'l', 'e'], 299 | }, 300 | ], 301 | '/amble/ /idle/', 302 | ); 303 | } 304 | 305 | { 306 | my $ra = Regexp::Assemble->new; 307 | $ra->insert( qw/a m b l e/ ); 308 | $ra->insert( qw/a m p l e/ ); 309 | $ra->insert( qw/i d l e/ ); 310 | is_deeply( $ra->_path, 311 | [ 312 | { 313 | 'a' => [ 314 | 'a', 'm', 315 | { 316 | 'b' => [ 'b', 'l', 'e' ], 317 | 'p' => [ 'p', 'l', 'e' ], 318 | }, 319 | ], 320 | 'i' => ['i', 'd', 'l', 'e'], 321 | }, 322 | ], 323 | '/amble/ /ample/ /idle/', 324 | ); 325 | } 326 | 327 | { 328 | my $ra = Regexp::Assemble->new; 329 | $ra->insert( qw/d a m/ ); 330 | $ra->insert( qw/d a r e/ ); 331 | is_deeply( $ra->_path, 332 | [ 333 | 'd', 'a', 334 | { 335 | 'm' => ['m'], 336 | 'r' => ['r', 'e'], 337 | , 338 | }, 339 | ], 340 | '/dam/ /dare/', 341 | ); 342 | } 343 | 344 | { 345 | my $ra = Regexp::Assemble->new 346 | ->insert(qw/d a/) 347 | ->insert(qw/d b/) 348 | ->insert(qw/d c/) 349 | ; 350 | is_deeply( $ra->_path, 351 | [ 352 | 'd', 353 | { 354 | 'a' => ['a'], 355 | 'b' => ['b'], 356 | 'c' => ['c'], 357 | }, 358 | ], 359 | '/da/ /db/ /dc/', 360 | ); 361 | } 362 | 363 | { 364 | my $ra = Regexp::Assemble->new 365 | ->insert(qw/d a/) 366 | ->insert(qw/d b c d/) 367 | ->insert(qw/d c/) 368 | ; 369 | is_deeply( $ra->_path, 370 | [ 371 | 'd', 372 | { 373 | 'a' => ['a'], 374 | 'b' => ['b', 'c', 'd'], 375 | 'c' => ['c'], 376 | }, 377 | ], 378 | '/da/ /dbcd/ /dc/', 379 | ); 380 | } 381 | 382 | sub permute { 383 | my $target = shift; 384 | my $path = shift; 385 | my( $x1, $x2, $x3, $x4, $x5 ); 386 | for $x1( 0..4 ) { 387 | for $x2( 0..4 ) { 388 | next if $x2 == $x1; 389 | for $x3( 0..4 ) { 390 | next if grep { $_ == $x3 } ($x1, $x2); 391 | for $x4( 0..4 ) { 392 | next if grep { $_ == $x4 } ($x1, $x2, $x3); 393 | for $x5( 0..4 ) { 394 | next if grep { $_ == $x5 } ($x1, $x2, $x3, $x4); 395 | my $ra = Regexp::Assemble->new 396 | ->insert( @{$path->[$x1]} ) 397 | ->insert( @{$path->[$x2]} ) 398 | ->insert( @{$path->[$x3]} ) 399 | ->insert( @{$path->[$x4]} ) 400 | ->insert( @{$path->[$x5]} ) 401 | ; 402 | is_deeply( $ra->_path, $target, 403 | '/' . join( '/ /', 404 | join( '' => @{$path->[$x1]}), 405 | join( '' => @{$path->[$x2]}), 406 | join( '' => @{$path->[$x3]}), 407 | join( '' => @{$path->[$x4]}), 408 | join( '' => @{$path->[$x5]}), 409 | ) . '/' 410 | ) or diag( 411 | $ra->dump(), 412 | ' versus ', 413 | Regexp::Assemble->_dump($target), 414 | "\n", 415 | ); 416 | } 417 | } 418 | } 419 | } 420 | } 421 | } 422 | 423 | permute( 424 | [ 425 | 'a', { 426 | '' => undef, 'b' => [ 427 | 'b', { 428 | '' => undef, 'c' => [ 429 | 'c', { 430 | '' => undef, 'd' => [ 431 | 'd', { 432 | '' => undef, 'e' => [ 433 | 'e', 434 | ], 435 | }, 436 | ], 437 | }, 438 | ], 439 | }, 440 | ], 441 | }, 442 | ], 443 | [ 444 | [ 'a', ], 445 | [ 'a', 'b' ], 446 | [ 'a', 'b', 'c' ], 447 | [ 'a', 'b', 'c', 'd' ], 448 | [ 'a', 'b', 'c', 'd', 'e' ], 449 | ] 450 | ); 451 | 452 | permute( 453 | [ 454 | { 455 | '' => undef, 'a' => [ 456 | 'a', { 457 | '' => undef, 'b' => [ 458 | 'b', { 459 | '' => undef, 'c' => [ 460 | 'c', { 461 | '' => undef, 'd' => [ 462 | 'd', 463 | ], 464 | }, 465 | ], 466 | }, 467 | ], 468 | }, 469 | ], 470 | }, 471 | ], 472 | [ 473 | [ '', ], 474 | [ 'a', ], 475 | [ 'a', 'b' ], 476 | [ 'a', 'b', 'c' ], 477 | [ 'a', 'b', 'c', 'd' ], 478 | ] 479 | ); 480 | 481 | permute( 482 | [ 'd', 'o', 483 | { 484 | 'n' => [ 485 | 'n', 'a', 't', 486 | { 487 | 'e' => ['e'], 488 | 'i' => ['i', 'o', 'n'], 489 | }, 490 | ] 491 | , 492 | 't' => [ 493 | 't', 494 | { 495 | 'a' => ['a', 't', 'e'], 496 | 'i' => ['i', 'n', 'g'], 497 | }, 498 | ], 499 | , 500 | '' => undef, 501 | }], 502 | [ 503 | [ split //, 'do' ], 504 | [ split //, 'donate' ], 505 | [ split //, 'donation' ], 506 | [ split //, 'dotate' ], 507 | [ split //, 'doting' ], 508 | ] 509 | ); 510 | 511 | permute( 512 | [ 513 | 'o', 514 | { 515 | '' => undef, 516 | 'n' => [ 517 | 'n', { 518 | '' => undef, 519 | 'l' => ['l', 'y'], 520 | 'e' => [ 521 | 'e', { 522 | '' => undef, 523 | 'r' => ['r'], 524 | } 525 | ], 526 | }, 527 | ], 528 | }, 529 | ], 530 | [ 531 | [ split //, 'o' ], 532 | [ split //, 'on' ], 533 | [ split //, 'one' ], 534 | [ split //, 'only' ], 535 | [ split //, 'oner' ], 536 | ], 537 | ); 538 | 539 | permute( 540 | [ 541 | 'a', 'm', 542 | { 543 | 'a' => [ 'a', 544 | { 545 | 's' => ['s', 's'], 546 | 'z' => ['z', 'e'], 547 | }, 548 | ], 549 | 'u' => [ 'u', 550 | { 551 | 'c' => ['c', 'k'], 552 | 's' => ['s', 'e'], 553 | } 554 | ], 555 | 'b' => [ 'b', 'l', 'e' ], 556 | }, 557 | ], 558 | [ 559 | [ split //, 'amass' ], 560 | [ split //, 'amaze' ], 561 | [ split //, 'amble' ], 562 | [ split //, 'amuck' ], 563 | [ split //, 'amuse' ], 564 | ], 565 | ); 566 | 567 | Regexp::Assemble::Default_Lexer( '\([^(]*(?:\([^)]*\))?[^)]*\)|.' ); 568 | 569 | { 570 | my $r = Regexp::Assemble->new; 571 | 572 | $r->reset->add( 'ab(cd)ef' ); 573 | is_deeply( $r->_path, 574 | [ 'a', 'b', '(cd)', 'e', 'f' ], 575 | 'ab(cd)ef (with Default parenthetical lexer)' 576 | ) or diag("lex = $r->{lex}"); 577 | 578 | $r->reset->add( 'ab((ef)gh)ij' ); 579 | is_deeply( $r->_path, 580 | [ 'a', 'b', '((ef)gh)', 'i', 'j' ], 581 | 'ab((ef)gh)ij (with Default parenthetical lexer)' 582 | ); 583 | 584 | $r->reset->add( 'ab(ef(gh))ij' ); 585 | is_deeply( $r->_path, 586 | [ 'a', 'b', '(ef(gh))', 'i', 'j' ], 587 | 'ab(ef(gh))ij (with Default parenthetical lexer)' 588 | ); 589 | 590 | eval { $r->filter('choke') }; 591 | ok( $@, 'die on non-CODE filter' ); 592 | 593 | eval { $r->pre_filter('choke') }; 594 | ok( $@, 'die on non-CODE pre_filter' ); 595 | } 596 | 597 | is( $_, $fixed, '$_ has not been altered' ); 598 | -------------------------------------------------------------------------------- /t/06_general.t: -------------------------------------------------------------------------------- 1 | # 06_general.t 2 | # 3 | # Test suite for Regexp::Assemble 4 | # Check out the general functionality, now that all the subsystems have been exercised 5 | # 6 | # copyright (C) 2004-2007 David Landgren 7 | 8 | use strict; 9 | use Regexp::Assemble; 10 | 11 | eval qq{use Test::More tests => 142 }; 12 | if( $@ ) { 13 | warn "# Test::More not available, no tests performed\n"; 14 | print "1..1\nok 1\n"; 15 | exit 0; 16 | } 17 | 18 | use constant NR_GOOD => 45; 19 | use constant NR_BAD => 529; 20 | use constant NR_ERROR => 0; 21 | 22 | my $fixed = 'The scalar remains the same'; 23 | $_ = $fixed; 24 | 25 | my $target; 26 | my $ra = Regexp::Assemble->new->add( qw/foo bar rat/ ); 27 | 28 | for $target( qw/unfooled disembark vibration/ ) { 29 | like( $target, qr/$ra/, "match ok $target" ) 30 | } 31 | 32 | ok( !defined($ra->source()), 'source() undefined' ); 33 | 34 | for $target( qw/unfooled disembark vibration/ ) { 35 | unlike( $target, qr/^$ra/, "anchored match not ok $target" ) 36 | } 37 | 38 | $ra->reset; 39 | 40 | for $target( qw/unfooled disembark vibration/ ) { 41 | unlike( $target, qr/$ra/, "fail after reset $target" ) 42 | } 43 | 44 | $ra->add( qw/who what where why when/ ); 45 | 46 | for $target( qw/unfooled disembark vibration/ ) { 47 | unlike( $target, qr/$ra/, "fail ok $target" ) 48 | } 49 | 50 | for $target( qw/snowhouse somewhat nowhereness whyever nowhence/ ) { 51 | like( $target, qr/$ra/, "new match ok $target" ) 52 | } 53 | 54 | $ra->reset->mutable(1); 55 | 56 | unlike( 'nothing', qr/$ra/, "match nothing after reset" ); 57 | 58 | $ra->add( '^foo\\d+' ); 59 | 60 | like( 'foo12', qr/$ra/, "match 1 ok foo12" ); 61 | unlike( 'nfoo12', qr/$ra/, "match 1 nok nfoo12" ); 62 | unlike( 'bar6', qr/$ra/, "match 1 nok bar6" ); 63 | 64 | ok( !defined($ra->mvar()), 'mvar() undefined' ); 65 | 66 | $ra->add( 'bar\\d+' ); 67 | 68 | like( 'foo12', qr/$ra/, "match 2 ok foo12" ); 69 | unlike( 'nfoo12', qr/$ra/, "match 2 nok nfoo12" ); 70 | like( 'bar6', qr/$ra/, "match 2 ok bar6" ); 71 | 72 | $ra->reset->filter( sub { not grep { $_ !~ /[\d ]/ } @_ } ); 73 | 74 | $ra->add( '1 2 4' ); 75 | $ra->insert( '1', '2', '8*' ); 76 | 77 | unlike( '3 4 1 2', qr/$ra/, 'filter nok 3 4 1 2' ); 78 | like( '3 1 2 4', qr/$ra/, 'filter ok 3 1 2 4' ); 79 | unlike( '5 2 3 4', qr/$ra/, 'filter ok 5 2 3 4' ); 80 | 81 | $ra->add( '2 3 a+' ); 82 | $ra->insert( '2', ' ', '3', ' ', 'a+' ); 83 | 84 | unlike( '5 2 3 4', qr/$ra/, 'filter ok 5 2 3 4 (2)' ); 85 | unlike( '5 2 3 aaa', qr/$ra/, 'filter nok 5 2 3 a+' ); 86 | 87 | $ra->reset->filter( undef ); 88 | 89 | $ra->add( '1 2 a+' ); 90 | like( '5 1 2 aaaa', qr/$ra/, 'filter now ok 5 1 2 a+' ); 91 | 92 | $ra->reset->pre_filter( sub { $_[0] !~ /^#/ } ); 93 | $ra->add( '#de' ); 94 | $ra->add( 'abc' ); 95 | 96 | unlike( '#de', qr/^$ra$/, '#de not matched by comment-filtered assembly' ); 97 | like( 'abc', qr/^$ra$/, 'abc matched by comment-filtered assembly' ); 98 | 99 | SKIP: { 100 | skip( "is_deeply is broken in this version of Test::More (v$Test::More::VERSION)", 5 ) 101 | unless $Test::More::VERSION > 0.47; 102 | 103 | { 104 | my $orig = Regexp::Assemble->new; 105 | my $clone = $orig->clone; 106 | is_deeply( $orig, $clone, 'clone empty' ); 107 | } 108 | 109 | { 110 | my $orig = Regexp::Assemble->new->add( qw/ dig dug dog / ); 111 | my $clone = $orig->clone; 112 | is_deeply( $orig, $clone, 'clone path' ); 113 | } 114 | 115 | { 116 | my $orig = Regexp::Assemble->new->add( qw/ dig dug dog / ); 117 | my $clone = $orig->clone; 118 | $orig->add( 'digger' ); 119 | $clone->add( 'digger' ); 120 | is_deeply( $orig, $clone, 'clone then add' ); 121 | } 122 | 123 | { 124 | my $orig = Regexp::Assemble->new 125 | ->add( qw/ bird cat dog elephant fox/ ); 126 | my $clone = $orig->clone; 127 | is_deeply( $orig, $clone, 'clone node' ); 128 | } 129 | 130 | { 131 | my $orig = Regexp::Assemble->new 132 | ->add( qw/ after alter amber cheer steer / ); 133 | my $clone = $orig->clone; 134 | is_deeply( $orig, $clone, 'clone more' ); 135 | } 136 | } 137 | 138 | SKIP: { 139 | # If the Storable module is available, we will have used 140 | # that above, however, we will not have tested the pure-Perl 141 | # fallback routines. 142 | skip( 'Pure-Perl clone() already tested', 5 ) 143 | unless $Regexp::Assemble::have_Storable; 144 | 145 | skip( "is_deeply is broken in this version of Test::More (v$Test::More::VERSION)", 5 ) 146 | unless $Test::More::VERSION > 0.47; 147 | 148 | local $Regexp::Assemble::have_Storable = 0; 149 | { 150 | my $orig = Regexp::Assemble->new; 151 | my $clone = $orig->clone; 152 | is_deeply( $orig, $clone, 'clone empty' ); 153 | } 154 | 155 | { 156 | my $orig = Regexp::Assemble->new->add( qw/ dig dug dog / ); 157 | my $clone = $orig->clone; 158 | is_deeply( $orig, $clone, 'clone path' ); 159 | } 160 | 161 | { 162 | my $orig = Regexp::Assemble->new->add( qw/ dig dug dog / ); 163 | my $clone = $orig->clone; 164 | $orig->add( 'digger' ); 165 | $clone->add( 'digger' ); 166 | is_deeply( $orig, $clone, 'clone then add' ); 167 | } 168 | 169 | { 170 | my $orig = Regexp::Assemble->new 171 | ->add( qw/ bird cat dog elephant fox/ ); 172 | my $clone = $orig->clone; 173 | is_deeply( $orig, $clone, 'clone node' ); 174 | } 175 | 176 | { 177 | my $orig = Regexp::Assemble->new 178 | ->add( qw/ after alter amber cheer steer / ); 179 | my $clone = $orig->clone; 180 | is_deeply( $orig, $clone, 'clone more' ); 181 | } 182 | } 183 | 184 | { 185 | my $r = Regexp::Assemble->new ->add( qw/ dig dug / ); 186 | cmp_ok( $r->dump, 'eq', '[d {i=>[i g] u=>[u g]}]', 'dump path' ); 187 | } 188 | 189 | { 190 | my $r = Regexp::Assemble->new ->add( 'a b' ); 191 | cmp_ok( $r->dump, 'eq', q<[a ' ' b]>, 'dump path with space' ); 192 | $r->insert( 'a', ' ', 'b', 'c', 'd' ); 193 | cmp_ok( $r->dump, 'eq', q([a ' ' b {* c=>[c d]}]), 194 | 'dump path with space 2' ); 195 | } 196 | 197 | { 198 | my $r = Regexp::Assemble->new ->add( qw/ dog cat / ); 199 | cmp_ok( $r->dump, 'eq', '[{c=>[c a t] d=>[d o g]}]', 'dump node' ); 200 | } 201 | 202 | { 203 | my $r = Regexp::Assemble->new->add( qw/ house home / ); 204 | $r->insert(); 205 | cmp_ok( $r->dump, 'eq', '[{* h=>[h o {m=>[m e] u=>[u s e]}]}]', 206 | 'add opt to path' ); 207 | } 208 | 209 | { 210 | my $r = Regexp::Assemble->new->add( qw/ dog cat / ); 211 | $r->insert(); 212 | cmp_ok( $r->dump, 'eq', '[{* c=>[c a t] d=>[d o g]}]', 213 | 'add opt to node' ); 214 | } 215 | 216 | { 217 | my $slide = Regexp::Assemble->new; 218 | cmp_ok( $slide->add( qw/schoolkids acids acidoids/ )->as_string, 219 | 'eq', '(?:ac(?:ido)?|schoolk)ids', 'schoolkids acids acidoids' ); 220 | 221 | cmp_ok( $slide->add( qw/schoolkids acidoids/ )->as_string, 222 | 'eq', '(?:schoolk|acido)ids', 'schoolkids acidoids' ); 223 | 224 | cmp_ok( $slide->add( qw/nonschoolkids nonacidoids/ )->as_string, 225 | 'eq', 'non(?:schoolk|acido)ids', 'nonschoolkids nonacidoids' ); 226 | } 227 | 228 | { 229 | cmp_ok( Regexp::Assemble->new 230 | ->add( qw( sing singing )) 231 | ->as_string, 'eq', 'sing(?:ing)?', 'super slide sing singing' # no sliding done 232 | ); 233 | 234 | cmp_ok( Regexp::Assemble->new 235 | ->add( qw( sing singing sling)) 236 | ->as_string, 'eq', 's(?:(?:ing)?|l)ing', 237 | 'super slide sing singing sling' 238 | ); 239 | 240 | cmp_ok( Regexp::Assemble->new 241 | ->add( qw( sing singing sling slinging)) 242 | ->as_string, 'eq', 'sl?(?:ing)?ing', 243 | 'super slide sing singing sling slinging' 244 | ); 245 | 246 | cmp_ok( Regexp::Assemble->new 247 | ->add( qw( sing singing sling slinging sting stinging )) 248 | ->as_string, 'eq', 's[lt]?(?:ing)?ing', 249 | 'super slide sing singing sling slinging sting stinging' 250 | ); 251 | 252 | cmp_ok( Regexp::Assemble->new 253 | ->add( qw( sing singing sling slinging sting stinging string stringing swing swinging )) 254 | ->as_string, 'eq', 's(?:[lw]|tr?)?(?:ing)?ing', 255 | 'super slide sing singing sling slinging sting stinging string stringing swing swinging' 256 | ); 257 | } 258 | { 259 | my $re = Regexp::Assemble->new( flags => 'i' )->add( qw/ ^ab ^are de / ); 260 | like( 'able', qr/$re/, '{^ab ^are de} /i matches able' ); 261 | like( 'About', qr/$re/, '{^ab ^are de} /i matches About' ); 262 | unlike( 'bare', qr/$re/, '{^ab ^are de} /i fails bare' ); 263 | like( 'death', qr/$re/, '{^ab ^are de} /i matches death' ); 264 | like( 'DEEP', qr/$re/, '{^ab ^are de} /i matches DEEP' ); 265 | } 266 | 267 | { 268 | my $re = Regexp::Assemble->new->add( qw/abc def ghi/ ); 269 | cmp_ok( $re->{stats_add}, '==', 3, "stats add 3x3" ); 270 | cmp_ok( $re->{stats_raw}, '==', 9, "stats raw 3x3" ); 271 | cmp_ok( $re->{stats_cooked}, '==', 9, "stats cooked 3x3" ); 272 | ok( !defined($re->{stats_dup}), "stats dup 3x3" ); 273 | 274 | $re->add( 'de' ); 275 | cmp_ok( $re->{stats_add}, '==', 4, "stats add 3x3 +1" ); 276 | cmp_ok( $re->{stats_raw}, '==', 11, "stats raw 3x3 +1" ); 277 | cmp_ok( $re->{stats_cooked}, '==', 11, "stats cooked 3x3 +1" ); 278 | } 279 | 280 | { 281 | my $re = Regexp::Assemble->new->add( '\\Qabc.def.ghi\\E' ); 282 | cmp_ok( $re->{stats_add}, '==', 1, "stats add qm" ); 283 | cmp_ok( $re->{stats_raw}, '==', 15, "stats raw qm" ); 284 | cmp_ok( $re->{stats_cooked}, '==', 13, "stats cooked qm" ); 285 | ok( !defined($re->{stats_dup}), "stats dup qm" ); 286 | } 287 | 288 | { 289 | my $re = Regexp::Assemble->new->add( 'abc\\,def', 'abc\\,def' ); 290 | cmp_ok( $re->{stats_add}, '==', 1, "stats add unqm dup" ); 291 | cmp_ok( $re->{stats_raw}, '==', 16, "stats raw unqm dup" ); 292 | cmp_ok( $re->{stats_cooked}, '==', 7, "stats cooked unqm dup" ); 293 | cmp_ok( $re->{stats_dup}, '==', 1, "stats dup unqm dup" ); 294 | cmp_ok( $re->stats_length, '==', 0, "stats_length unqm dup" ); 295 | 296 | my $str = $re->as_string; 297 | cmp_ok( $str, 'eq', 'abc,def', "stats str unqm dup" ); 298 | cmp_ok( $re->stats_length, '==', 7, "stats len unqm dup" ); 299 | } 300 | 301 | { 302 | my $re = Regexp::Assemble->new->add( '' ); 303 | cmp_ok( $re->{stats_add}, '==', 1, "stats add empty" ); 304 | cmp_ok( $re->{stats_raw}, '==', 0, "stats raw empty" ); 305 | ok( !defined($re->{stats_cooked}), "stats cooked empty" ); 306 | ok( !defined($re->{stats_dup}), "stats dup empty" ); 307 | } 308 | 309 | { 310 | my $re = Regexp::Assemble->new; 311 | cmp_ok( $re->stats_add, '==', 0, "stats_add empty" ); 312 | cmp_ok( $re->stats_raw, '==', 0, "stats_raw empty" ); 313 | cmp_ok( $re->stats_cooked, '==', 0, "stats_cooked empty" ); 314 | cmp_ok( $re->stats_dup, '==', 0, "stats_dup empty" ); 315 | cmp_ok( $re->stats_length, '==', 0, "stats_length empty" ); 316 | 317 | my $str = $re->as_string; 318 | cmp_ok( $str, 'eq', $Regexp::Assemble::Always_Fail, "stats str empty" ); # tricky! 319 | cmp_ok( $re->stats_length, '==', 0, "stats len empty" ); 320 | } 321 | 322 | { 323 | my $re = Regexp::Assemble->new->add( '\\Q.+\\E', '\\Q.+\\E', '\\Q.*\\E' ); 324 | cmp_ok( $re->stats_add, '==', 2, "stats_add 2" ); 325 | cmp_ok( $re->stats_raw, '==', 18, "stats_raw 2" ); 326 | cmp_ok( $re->stats_cooked, '==', 8, "stats_cooked 2" ); 327 | cmp_ok( $re->stats_dup, '==', 1, "stats_dup 2" ); 328 | cmp_ok( $re->stats_length, '==', 0, "stats_length 2" ); 329 | 330 | my $str = $re->as_string; 331 | cmp_ok( $str, 'eq', '\\.[*+]', "stats str 2" ); 332 | cmp_ok( $re->stats_length, '==', 6, "stats len 2 <$str>" ); 333 | } 334 | 335 | { 336 | # CPAN bug #24171 337 | # given a list of strings 338 | my @str = ( 'a b', 'awb', 'a1b', 'bar', "a\nb" ); 339 | 340 | for my $meta (qw( s w d )) { 341 | 342 | # given a list of patterns 343 | my @re = ( "a\\${meta}b", "a\\@{[uc$meta]}b" ); 344 | 345 | # produce an assembled pattern 346 | my $re = Regexp::Assemble->new()->add(@re)->re(); 347 | 348 | my $re_fold = Regexp::Assemble->new()->fold_meta_pairs(0)->add(@re)->re(); 349 | 350 | # test it against the strings 351 | for my $str (@str) { 352 | 353 | # any match? 354 | my $ok = 0; 355 | $str =~ $_ && ( $ok = 1 ) for @re; 356 | 357 | # does the assemble regexp match as well? 358 | my $ptr = $str; 359 | $ptr =~ s/\\/\\\\/; 360 | $ptr =~ s/\n/\\n/; 361 | 362 | my $bug_success = ($str =~ /\n/) ? 0 : 1; 363 | my $bug_fail = 1 - $bug_success; 364 | 365 | is( ($str =~ $re) ? $bug_success : $bug_fail, $ok, 366 | "Folded meta pairs behave as list for \\$meta ($ptr,ok=$ok/$bug_success/$bug_fail)" 367 | ); 368 | 369 | is( ($str =~ $re_fold) ? 1 : 0, $ok, 370 | "Unfolded meta pairs behave as list for \\$meta ($ptr,ok=$ok)" 371 | ); 372 | 373 | } 374 | } 375 | } 376 | 377 | { 378 | my $u = Regexp::Assemble->new(unroll_plus => 1); 379 | my $str; 380 | 381 | $u->add( "a+b", 'ac' ); 382 | $str = $u->as_string; 383 | is( $str, 'a(?:a*b|c)', 'unroll plus a+b ac' ); 384 | 385 | $u->add( "\\LA+B", "ac" ); 386 | $str = $u->as_string; 387 | is( $str, 'a(?:a*b|c)', 'unroll plus \\LA+B ac' ); 388 | 389 | $u->add( '\\Ua+?b', "AC" ); 390 | $str = $u->as_string; 391 | is( $str, 'A(?:A*?B|C)', 'unroll plus \\Ua+?b AC' ); 392 | 393 | $u->add( qw(\\d+d \\de \\w+?x \\wy )); 394 | $str = $u->as_string; 395 | is( $str, '(?:\\w(?:\\w*?x|y)|\\d(?:\d*d|e))', 'unroll plus \\d and \\w' ); 396 | 397 | $u->add( qw( \\xab+f \\xabg \\xcd+?h \\xcdi )); 398 | $str = $u->as_string; 399 | is( $str, "(?:\xcd(?:\xcd*?h|i)|\xab(?:\xab*f|g))", 'unroll plus meta x' ); 400 | 401 | $u->add( qw([a-e]+h [a-e]i [f-j]+?k [f-j]m )); 402 | $str = $u->as_string; 403 | is( $str, "(?:[f-j](?:[f-j]*?k|m)|[a-e](?:[a-e]*h|i))", 'unroll plus class' ); 404 | 405 | $u->add( "a+b" ); 406 | $str = $u->as_string; 407 | is( $str, "a+b", 'reroll a+b' ); 408 | 409 | $u->add( "a+b", "a+" ); 410 | $str = $u->as_string; 411 | is( $str, "a+b?", 'reroll a+b?' ); 412 | 413 | $u->add( "a+?b", "a+?" ); 414 | $str = $u->as_string; 415 | is( $str, "a+?b?", 'reroll a+?b?' ); 416 | 417 | $u->unroll_plus(0)->add( qw(1+2 13) ); 418 | $str = $u->as_string; 419 | is( $str, "(?:1+2|13)", 'no unrolling' ); 420 | 421 | $u->unroll_plus()->add( qw(1+2 13) ); 422 | $str = $u->as_string; 423 | is( $str, "1(?:1*2|3)", 'unrolling again via implicit' ); 424 | 425 | $u->add(qw(d+ldrt d+ndrt d+ldt d+ndt d+x)); 426 | $str = $u->as_string; 427 | is( $str, 'd+(?:[ln]dr?t|x)', 'visit ARRAY codepath' ); 428 | } 429 | 430 | cmp_ok( $_, 'eq', $fixed, '$_ has not been altered' ); 431 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This file is the README for Regexp::Assemble version 0.35 2 | 3 | INSTALLATION 4 | 5 | perl Makefile.PL 6 | make 7 | make test 8 | make install 9 | 10 | TESTING 11 | 12 | This module requires the following modules for thorough testing: 13 | 14 | Test::More 15 | Test::File::Contents 16 | Test::Pod 17 | Test::Pod::Coverage 18 | Test::Warn 19 | 20 | The test suite will make allowances for their eventual absence. 21 | 22 | It can also make use of Devel::Cover if available. 23 | 24 | UNINSTALLATION 25 | 26 | This is a pure-Perl module. The following one-liner should print 27 | out the canonical path of the file: 28 | 29 | perl -MRegexp::Assemble -le 'print $INC{"Regexp/Assemble.pm"}' 30 | 31 | Just delete this file. There is also the question of the man page. 32 | Finding that is left as an exercise to the reader. 33 | 34 | BASIC USAGE 35 | 36 | use Regexp::Assemble; 37 | 38 | my $ra = Regexp::Assemble->new; 39 | $ra->add( 'ab+c' ); 40 | $ra->add( 'ab+\\d*\\s+c' ); 41 | $ra->add( 'a\\w+\\d+' ); 42 | $ra->add( 'a\\d+' ); 43 | print $ra->re; # prints (?:a(?:b+(?:\d*\s+)?c|(?:\w+)?\d+)) 44 | 45 | or 46 | 47 | my $ra = Regexp::Assemble->new 48 | ->add( 'foo', 'bar', 'baz', 'foom' ); 49 | 50 | print "$_ matches\n" if /$ra/ 51 | for (qw/word more stuff food rabble bark/); 52 | 53 | or 54 | 55 | use Regexp::Assemble; 56 | my @word = qw/flip flop slip slop/; 57 | 58 | print Regexp::Assemble->new->add(@word)->as_string; 59 | # produces [fs]l[io]p 60 | 61 | print Regexp::Assemble->new->add(@word)->reduce(0)->as_string; 62 | # produces (?:fl(?:ip|op)|sl(?:ip|op)) 63 | 64 | See the ./eg directory for some example scripts. 65 | 66 | ADVANCED USAGE 67 | 68 | If you want to match things with exceptions, you can use a two 69 | stage process to build a pattern with negative lookbehind. Consider 70 | the following script: 71 | 72 | == example begin == 73 | use Regexp::Assemble; 74 | 75 | my $set = [ 76 | { 77 | accept => [qw[ .cnn.net .cnn.com ]], 78 | refuse => [qw[ ^media video ]], 79 | }, 80 | { 81 | accept => [qw[ .yahoo.com ]], 82 | }, 83 | ]; 84 | 85 | my $ra = Regexp::Assemble->new; 86 | 87 | for my $s( @$set ) { 88 | my $refuse = do { 89 | if( not exists $s->{refuse} ) { 90 | ''; 91 | } 92 | else { 93 | '(?new->add( @{$s->{refuse}} )->as_string 95 | . ')' 96 | } 97 | }; 98 | $ra->add( map { s/\./\\./g; "$refuse$_\$" } @{$s->{accept}} ); 99 | } 100 | 101 | my $re = $ra->re; 102 | 103 | print $ra->as_string, "\n"; 104 | 105 | while( <> ) { 106 | print; 107 | chomp; 108 | print "\t", (/$re/ ? 'yep' : 'nope'), "\n"; 109 | } 110 | 111 | == example end == 112 | 113 | and a datafile to run it on: 114 | 115 | == data begin == 116 | media.cnn.com 117 | more.video.cnn.net 118 | super.media.cnn.com 119 | video.cnn.net 120 | video.yahoo.com 121 | www.cnn.com 122 | www.cnn.net 123 | www.yahoo.com 124 | == data end == 125 | 126 | This lets us match arbitrary hosts within a domain, but at the same 127 | time excluding a subset of hosts that we wish to ignore. 128 | 129 | TRACKING REGULAR EXPRESSION MATCHES 130 | 131 | Regexp::Assemble can emit regular expressions that, when used correctly, 132 | can let you determine which original pattern gave rise to the match. 133 | This technique is known as tracking. 134 | 135 | == example begin == 136 | 137 | use strict; 138 | use Regexp::Assemble; 139 | 140 | my $dispatch = { 141 | 'a-(\\d+)' => sub { my $v = shift; print "speed $v->[1]\n"; }, 142 | 'a-(\\d+)-(\\d+)' => sub { my $v = shift; print "pressure $v->[1] over $v->[2]\n"; }, 143 | 'a-(\\w+)-(\\w+)' => sub { my $v = shift; print "message $v->[1] from $v->[2]\n"; }, 144 | }; 145 | 146 | my $re = Regexp::Assemble->new( track => 1 )->add( keys %$dispatch ); 147 | 148 | while( <> ) { 149 | chomp; 150 | if( $re->match($_) ) { 151 | $dispatch->{ $re->matched }( $re->mvar() ); 152 | } 153 | else { 154 | last if /q/; 155 | print "\tignored\n"; 156 | } 157 | } 158 | 159 | == example end == 160 | 161 | Run this and enter lines like a-234, a-654, a-345-345, a-dog-cat and so 162 | on. When the pattern matches a string, you can retrieve the pattern 163 | that caused the match to occur, and dispatch it to a routine that knows 164 | what to do about it. You can retrieve captured values too. In the above 165 | example, just remember that $v->[1] eq $1. $v->[0], a.k.a $re->mvar(0) 166 | happens to be the the same as the input parameter to match (although 167 | this is worked out from first principles, more or less, not simply by 168 | copying the parameter). 169 | 170 | I initially hoped that $^R would handle this sort of stuff for me, but 171 | there's a bug. Consider the following pattern: 172 | 173 | a(?{1}) (?: b(?{2}) )? 174 | 175 | (whitespace added for clarity). This pattern will match both the strings 176 | 'a' and 'ab', however, in both cases, $^R will be set to 1 aftewards. I 177 | would have hoped that after matching 'ab', that $^R would be set to 2. 178 | 179 | As of perl 5.9.5, this bug has been corrected in the regular expression 180 | engine, thanks to Yves Orton. Version 0.29 takes this into account, and 181 | as a result re 'eval' is no longer required in Perl 5.10. 182 | 183 | IMPLEMENTATION 184 | 185 | Consider a simple pattern 'costructive' we want to use to match against 186 | strings. This pattern is split into tokens, and is stored in a list: 187 | 188 | [c o n s t r u c t i v e] 189 | 190 | At this point, if we want to produce a regular expression, we only need 191 | to join it up again: 192 | 193 | my $pattern = join( '' => @path); 194 | my $re = qr/$pattern/; 195 | 196 | Consider a second pattern 'containment'. Split into a list gives: 197 | 198 | [c o n t a i n m e n t] 199 | 200 | We then have to merge this second path into the first path. At some 201 | point, the paths diverge. The first element path the point of 202 | divergence in the first path is replace by a node (a hash) and the two 203 | different paths carry on from there: 204 | 205 | [c o n 206 | |s => [s t r u c t i v e] 207 | \t => [t a i n m e n t] 208 | ] 209 | 210 | And then 'confinement': 211 | 212 | [c o n 213 | |s => [s t r u c t i v e] 214 | |t => [t a i n m e n t] 215 | \f => [f i n e m e n t] 216 | ] 217 | 218 | What happens if we add a path that runs out in the middle of a 219 | previous path? We add a node, and a "null-path" to indicate that 220 | the path can both continue on, and can also stop here: 221 | 222 | Add 'construct': 223 | 224 | [c o n 225 | |s => [s t r u c t 226 | | | '' => undef 227 | | \ i => [i v e] 228 | | ] 229 | |t => [t a i n m e n t] 230 | \f => [f i n e m e n t] 231 | ] 232 | 233 | It should be obvious to see how the contruct branch will produce the 234 | pattern /construct(?:ive)?/ . Or for a longer path 'constructively': 235 | 236 | [c o n 237 | |s => [s t r u c t 238 | | | '' => undef 239 | | \ i => [i v e 240 | | | '' => undef 241 | | \ l => [l y] 242 | | ] 243 | | ] 244 | |t => [t a i n m e n t] 245 | \f => [f i n e m e n t] 246 | ] 247 | 248 | This is the state of the internal structure before reduction. When 249 | traversed it will produce a valid regular expression. 250 | 251 | The trick is how to perform the reduction. The key insight is to note 252 | that for any part of the trunk where the sibling paths do not end in 253 | a node, it it possible to reverse them, and insert them into their 254 | own R::A object and see what comes out: 255 | 256 | [t a i n m e n t] => 257 | [t n e m n i a t] 258 | 259 | [f i n e m e n t] => 260 | [t n e m e n i f] 261 | 262 | Gives: 263 | 264 | [t n e m 265 | | n => [n i a t] 266 | \ e => [e n i f] 267 | ] 268 | 269 | When the algorithm visits the other path (s => [s t r u c t ...]), 270 | it behaves differently. When a null path is seen, no reduction is 271 | performed at that node level. The resulting path would otherwise 272 | begin to admit matches that are are not permitted by any of the 273 | initial patterns. For instance, with bat, cat, and catty, you can 274 | hardly try to merge 'bat' and 'cat' to produce [bc]at, otherwise the 275 | resulting pattern would become [bc]at(ty)?, and that would incorrectly 276 | match 'batty'. 277 | 278 | After having visited the s, t, and f paths, the 279 | result is that t and f were reduced, and s failed. We therefore 280 | unreverse everything, and signal that this node cannot participate in 281 | any more reduction (the failures percolate up the tree back to the 282 | root). 283 | 284 | Unreversing the t, f reduction gives: 285 | 286 | [ t => [t a i n] \ 287 | f => [f i n e] | m e n t ] 288 | 289 | When all is said and done, the final result gives 290 | 291 | [c o n 292 | |s => [s t r u c t 293 | | | '' => undef 294 | | \ i => [i v e 295 | | | '' => undef 296 | | \ l => [l y] 297 | | ] 298 | | ] 299 | [ t => [t a i n] 300 | f => [f i n e] m e n t ] 301 | ] 302 | 303 | When this data structure is traversed to build the pattern, it gives 304 | 305 | con(struct(ive(ly)?)?|(fine|tain)ment) 306 | 307 | NB: The capturing syntax is used here, instead of the grouping 308 | syntax for readability issues only. 309 | 310 | On the other hand, if the s path contained only [s t r u c t], then 311 | the reduction would have gone succeeded. We would have a common 312 | head [t], shared by all three paths. 313 | 314 | [t 315 | | c => [c u r t s] 316 | \ n => [n e m 317 | | n => [n i a t] 318 | \ e => [e n i f] 319 | ] 320 | ] 321 | 322 | And then consider that the path [c o u r t] had also been added to 323 | the object. We would then be able to reduce the t from the above 324 | reduction, and the t in [c o u r t] 325 | 326 | [c o 327 | | n => [n 328 | | | s => [s t r u c t] 329 | | | t => [t a i n m e n t] 330 | | \ f => [f i n e m e n t] 331 | | ] 332 | \ u => [u r t] 333 | ] 334 | 335 | gives 336 | 337 | [c o 338 | | n => [n 339 | | | s => [s t r u c] 340 | | \ f => [ 341 | | f => [f i n e] 342 | | t => [t a i n] 343 | | m e n 344 | | ] 345 | | ] 346 | \ u => [u r] 347 | t 348 | ] 349 | 350 | (Here ends my ASCII art talents). 351 | 352 | The above structure would give 353 | 354 | co(n(struc|(fine|tai)men)|ur)t 355 | 356 | In a nutshell, that's it. Seems like the code would be simple, huh? 357 | It turns out that no, there are lots of fiddly edge cases, 358 | especially sets of paths are the same as other sets of paths 359 | except for an optional sub-path. The canonical example that the 360 | test suite deals with is: 361 | 362 | showeriness, showerless, showiness, showless. 363 | 364 | The final pattern is 365 | 366 | show(er)?(in|l)ess 367 | 368 | If there are bugs to be found, it will be in cases that are even 369 | more pathological than this, e.g., something like: 370 | 371 | show(er)?(i(a|po)?n|l)ess 372 | 373 | (although the above actually *does* work, I tried it) 374 | 375 | TESTING STRATEGY USED 376 | 377 | The code has been heavily tested using an approach based on 378 | combinatoric lists known as power sets. For instance, the power 379 | set of (a,b,c,d) is (assuming a join() on the results): 380 | 381 | a ab abc abcd abd ac acd ad b bc bcd bd c cd d 382 | 383 | (along with the empty set). The power set of N elements contains 384 | 2**N elements. (or 2**N-1 of we exclude the empty set). 385 | 386 | The testing approach was then to take the power set of the above 387 | power set and produce regular expressions from each element. 388 | 389 | For instance, at some point, we would encounter the set 390 | 391 | abc ac bcd cd d 392 | 393 | From this we generate the pattern (?:(?:b?c)?d|ab?c). Once we have 394 | this pattern, we go back and check that it does in fact match the 395 | above 5 elements, and furthermore, that it does *not match* the 396 | remaining 10 elements of the power set not used in this iteration. 397 | 398 | And yes, that shook out a couple of bugs. 399 | 400 | As of this time, the following search space has been examined 401 | 402 | a b c - complete 403 | a b c d - complete 404 | a b c d e - runs of 1-11, 20-31 complete, 12-17 partial 405 | a b c d e f - runs of 1-5, 61-63 complete 406 | a b c d e f g - runs of 1-4, 125-127 complete 407 | 408 | The code for this is in the eg/stress-test script. Note: it can use 409 | months of CPU time if you're not careful. It requires the following 410 | modules: 411 | 412 | Algorithm::Combinatorics 413 | Data::PowerSet 414 | 415 | OTHER CONSIDERATIONS 416 | 417 | When tracking is in use, no reduction is performed. 418 | 419 | Pretty-printed (indented), and tracking is handled merely by calling 420 | different output routines. Each routine emits things in a different 421 | way, but the underlying structure remains the same. Which is one 422 | reason why you can't have pretty-printed tracked patterns (Well you 423 | can, but I haven't written the routine that would do so). 424 | 425 | Zero-width lookahead assertions can be added to the pattern. This may 426 | be a win, but it may also slow things down. 427 | 428 | DEBUGGING NOTES 429 | 430 | If you are curious, you can dump out the internal data struct with 431 | the following: 432 | 433 | use Data::Dumper; 434 | $Data::Dumper::Terse = 0; 435 | $Data::Dumper::Indent = 0; 436 | $Data::Dumper::Quotekeys = 0; 437 | $Data::Dumper::Pair = '=>'; 438 | 439 | print Dumper($r->_path); 440 | 441 | A more compact representation can be obtained with 442 | 443 | print $r->dump; 444 | 445 | All that said, I'm now reasonably confident that it deals 446 | correctly with pretty much anything you're likely to throw at it. 447 | 448 | Two recent bugs were easy to spot in the code, and the fix was a 449 | couple of lines. Adding lookahead assertion was pretty simple to, 450 | even if it did result in a certain amount of code factoring. So I 451 | think that in general the structure of the code is a good one. 452 | 453 | The eg/debugging script offers a good strategy for dealing with 454 | assemblies that give rise to uncompilable patterns. 455 | 456 | STATUS 457 | 458 | This module is under active development. The module is managed in 459 | a Subversion repository, and thus, the latest working copy is 460 | available at 461 | 462 | https://github.com/ronsavage/Regexp-Assemble 463 | 464 | AUTHOR 465 | 466 | David Landgren 467 | 468 | Ron Savage is co-maint of the module, starting with V 0.36. 469 | 470 | I do appreciate getting e-mail, especially about Perl. Please keep in 471 | mind that I get a lot of spam, and take drastic measures to reduce the 472 | flow. One of the measures involves a gigantic regular expression that 473 | contains many thousands of patterns that match hostnames of dynamic 474 | dialup/residential/home IP addresses. That pattern is of course built 475 | with this module. 476 | 477 | It would be ironic if I rejected your mail coming from such an address. 478 | Please use your ISP's outbound MX, or pay what it takes to get your 479 | reverse DNS changed to something else. 480 | 481 | COPYRIGHT 482 | 483 | This module is copyright (C) David Landgren 2004-2008. 484 | All rights reserved. 485 | 486 | LICENSE 487 | 488 | This library is free software; you can redistribute it and/or modify 489 | it under the same terms as Perl itself. 490 | -------------------------------------------------------------------------------- /examples/hostmatch/bad.canonical: -------------------------------------------------------------------------------- 1 | m194-158-65-134.andorpac.ad 2 | m194-158-83-34.andorpac.ad 3 | de11929.alshamil.net.ae 4 | de21057.alshamil.net.ae 5 | de23208.alshamil.net.ae 6 | de2334.alshamil.net.ae 7 | de23392.alshamil.net.ae 8 | de24037.alshamil.net.ae 9 | de24435.alshamil.net.ae 10 | de25655.alshamil.net.ae 11 | 106-172-89-200.fibertel.com.ar 12 | 106-186-89-200.fibertel.com.ar 13 | 114-196-126-200.fibertel.com.ar 14 | 12-142-126-200.fibertel.com.ar 15 | 140-208-114-200.fibertel.com.ar 16 | 148-148-114-200.fibertel.com.ar 17 | 148-230-114-200.fibertel.com.ar 18 | 188-137-89-200.fibertel.com.ar 19 | 200-155-126-200.fibertel.com.ar 20 | 207-181-89-200.fibertel.com.ar 21 | 224-130-89-200.fibertel.com.ar 22 | 240-196-114-200.fibertel.com.ar 23 | 241-156-114-200.fibertel.com.ar 24 | 241-251-114-200.fibertel.com.ar 25 | 26-159-114-200.fibertel.com.ar 26 | 40-140-126-200.fibertel.com.ar 27 | 5-242-114-200.fibertel.com.ar 28 | 76-191-89-200.fibertel.com.ar 29 | ol126-12.fibertel.com.ar 30 | ol13-78.fibertel.com.ar 31 | ol134-243.fibertel.com.ar 32 | ol146-22.fibertel.com.ar 33 | ol159-75.fibertel.com.ar 34 | ol169-14.fibertel.com.ar 35 | ol191-125.fibertel.com.ar 36 | ol196-185.fibertel.com.ar 37 | ol199-183.fibertel.com.ar 38 | ol243-132.fibertel.com.ar 39 | ol249-11.fibertel.com.ar 40 | ol249-56.fibertel.com.ar 41 | ol3-37.fibertel.com.ar 42 | ol30-250.fibertel.com.ar 43 | ol55-13.fibertel.com.ar 44 | ol57-192.fibertel.com.ar 45 | ol65-51.fibertel.com.ar 46 | ol68-150.fibertel.com.ar 47 | host13.200.80.24.ifxnw.com.ar 48 | int-200-49-220-42.movi.com.ar 49 | int-200-49-223-245.movi.com.ar 50 | host-239.28.60.66-ta.adsl.netizen.com.ar 51 | dsl-200-43-19-83.users.telpin.com.ar 52 | 200-112-152-211.bbt.net.ar 53 | 200-122-96-189.prima.net.ar 54 | 200-122-72-230.cab.prima.net.ar 55 | 200-122-72-242.cab.prima.net.ar 56 | 200-122-89-133.cab.prima.net.ar 57 | 200-122-89-187.cab.prima.net.ar 58 | 200-122-90-89.cab.prima.net.ar 59 | 200-42-86-250.cab.prima.net.ar 60 | 200-122-19-254.dsl.prima.net.ar 61 | 200-122-44-246.dsl.prima.net.ar 62 | 200-122-47-219.dsl.prima.net.ar 63 | 200-122-51-48.dsl.prima.net.ar 64 | 200-122-62-222.dsl.prima.net.ar 65 | 200-122-8-86.dsl.prima.net.ar 66 | 200-55-109-42.dsl.prima.net.ar 67 | 200-42-118-237.dup.prima.net.ar 68 | 200-42-27-86.dup.prima.net.ar 69 | 200-42-74-242.wll.prima.net.ar 70 | host3.200-117-255.telecom.net.ar 71 | host161.200-45-119.telecom.net.ar 72 | host9.200-45-119.telecom.net.ar 73 | host52.200-45-154.telecom.net.ar 74 | host10.200-45-234.telecom.net.ar 75 | host135.200-45-236.telecom.net.ar 76 | host53.201-252-211.telecom.net.ar 77 | host52.201-252-215.telecom.net.ar 78 | host23.201-252-89.telecom.net.ar 79 | chello213047046194.1.sc-graz.chello.at 80 | chello080109200248.3.sc-graz.chello.at 81 | 83-64-21-44.dynamic.home.xdsl-line.inode.at 82 | 81-223-84-107.paris-lodron.xdsl-line.inode.at 83 | h081217134143.dyn.cm.kabsi.at 84 | h062040180106.med.cm.kabsi.at 85 | h062040175110.moe.cm.kabsi.at 86 | cm101-198.liwest.at 87 | cm105-115.liwest.at 88 | cm127-80.liwest.at 89 | cm130-144.liwest.at 90 | cm133-85.liwest.at 91 | cm144-88.liwest.at 92 | cm152-253.liwest.at 93 | cm156-27.liwest.at 94 | cm176-247.liwest.at 95 | cm220-124.liwest.at 96 | cm238-223.liwest.at 97 | cm239-76.liwest.at 98 | cm240-25.liwest.at 99 | cm249-96.liwest.at 100 | cm62-144.liwest.at 101 | 217-25-113-249.pircher.at 102 | 195-70-102-67.dyn.salzburg-online.at 103 | 195-70-97-81.dyn.salzburg-online.at 104 | 213-153-47-21.dyn.salzburg-online.at 105 | 213-153-48-39.dyn.salzburg-online.at 106 | 82-194-133-193.dyn.salzburg-online.at 107 | 82-194-135-243.dyn.salzburg-online.at 108 | chello213047046108.1.graz.surfer.at 109 | chello080109197149.2.graz.surfer.at 110 | chello080109203248.4.graz.surfer.at 111 | chello080109219252.4.graz.surfer.at 112 | chello213047048050.4.graz.surfer.at 113 | chello084115129099.5.graz.surfer.at 114 | chello080109218197.6.graz.surfer.at 115 | chello212017123151.4.klafu.surfer.at 116 | chello080109132150.tirol.surfer.at 117 | chello080109140115.tirol.surfer.at 118 | chello080109143084.tirol.surfer.at 119 | chello080109164042.tirol.surfer.at 120 | chello062178035093.12.11.vie.surfer.at 121 | chello213047117026.13.11.vie.surfer.at 122 | chello062178052028.18.11.vie.surfer.at 123 | chello080108080045.18.11.vie.surfer.at 124 | chello212017114099.18.11.vie.surfer.at 125 | chello062178054043.19.11.vie.surfer.at 126 | chello212186109127.19.11.vie.surfer.at 127 | chello062178004217.2.11.vie.surfer.at 128 | chello062178059119.20.11.vie.surfer.at 129 | chello080108016046.20.11.vie.surfer.at 130 | chello080108053192.25.11.vie.surfer.at 131 | chello084112028116.25.11.vie.surfer.at 132 | chello062178080107.27.11.vie.surfer.at 133 | chello084112018017.27.11.vie.surfer.at 134 | chello080108036122.31.11.vie.surfer.at 135 | chello212186208124.32.11.vie.surfer.at 136 | chello212186123139.33.11.vie.surfer.at 137 | chello213047134251.33.11.vie.surfer.at 138 | chello212186162128.4.11.vie.surfer.at 139 | chello062178012122.5.11.vie.surfer.at 140 | chello212186105092.6.11.vie.surfer.at 141 | chello080108087243.7.11.vie.surfer.at 142 | chello080108100084.8.11.vie.surfer.at 143 | chello084112006132.8.11.vie.surfer.at 144 | chello062178185143.1.12.vie.surfer.at 145 | chello213047104145.1.12.vie.surfer.at 146 | chello062178230148.10.12.vie.surfer.at 147 | chello084113020081.2.12.vie.surfer.at 148 | chello080108137131.3.12.vie.surfer.at 149 | chello213047105222.3.12.vie.surfer.at 150 | chello080108151071.5.12.vie.surfer.at 151 | chello213047103203.6.12.vie.surfer.at 152 | chello080108168243.9.12.vie.surfer.at 153 | chello080108196048.1.13.vie.surfer.at 154 | chello080108198050.2.13.vie.surfer.at 155 | chello062178125241.3.13.vie.surfer.at 156 | chello080108220235.3.13.vie.surfer.at 157 | chello084113196053.1.14.vie.surfer.at 158 | chello062178164066.11.14.vie.surfer.at 159 | chello080109022046.11.14.vie.surfer.at 160 | chello213047087197.11.14.vie.surfer.at 161 | chello062178165114.12.14.vie.surfer.at 162 | chello084113002037.12.14.vie.surfer.at 163 | chello213047164075.13.14.vie.surfer.at 164 | chello080109053218.14.14.vie.surfer.at 165 | chello062178176224.15.14.vie.surfer.at 166 | chello062178179196.16.14.vie.surfer.at 167 | chello213047061057.2.14.vie.surfer.at 168 | chello212186068249.3.14.vie.surfer.at 169 | chello213047080068.4.14.vie.surfer.at 170 | chello080109092182.15.15.vie.surfer.at 171 | chello080109065078.17.15.vie.surfer.at 172 | chello062178190124.2.15.vie.surfer.at 173 | chello062178231059.3.15.vie.surfer.at 174 | chello080109074169.4.15.vie.surfer.at 175 | chello080109116237.4.15.vie.surfer.at 176 | d213-102-130-44.cust.tele2.at 177 | m097p028.adsl.highway.telekom.at 178 | m1524p010.adsl.highway.telekom.at 179 | m1945p003.adsl.highway.telekom.at 180 | m2236p004.adsl.highway.telekom.at 181 | m369p019.adsl.highway.telekom.at 182 | m763p027.adsl.highway.telekom.at 183 | m898p012.adsl.highway.telekom.at 184 | n219p025.adsl.highway.telekom.at 185 | l1420p29.dipool.highway.telekom.at 186 | chello062178018161.7.11.univie.teleweb.at 187 | chello212017075138.2.15.univie.teleweb.at 188 | chello062178195142.4.15.univie.teleweb.at 189 | chello062178024246.9.11.wu-wien.teleweb.at 190 | dsl-linz7-17-24.utaonline.at 191 | dialup-342.syd.ar.com.au 192 | dialup-246.152.220.203.acc01-ball-lis.comindico.com.au 193 | dialup-128.118.221.203.acc02-mcmi-dwn.comindico.com.au 194 | dsl-3.117.240.220.dsl.comindico.com.au 195 | 210-9-142-38.netspeed.com.au 196 | blaax10-a224.dialup.optusnet.com.au 197 | chtax3-069.dialup.optusnet.com.au 198 | lonax10-b172.dialup.optusnet.com.au 199 | rohax5-023.dialup.optusnet.com.au 200 | wayax5-131.dialup.optusnet.com.au 201 | winax22-179.dialup.optusnet.com.au 202 | wooax17-b154.dialup.optusnet.com.au 203 | d211-29-190-138.dsl.nsw.optusnet.com.au 204 | d211-31-90-216.dsl.nsw.optusnet.com.au 205 | d220-236-28-253.dsl.nsw.optusnet.com.au 206 | c211-28-155-233.eburwd2.vic.optusnet.com.au 207 | c210-49-192-205.lowrp1.vic.optusnet.com.au 208 | 81.fip-213.permisdn.ozemail.com.au 209 | 203-219-27-145-bri-ts4-2600.tpgi.com.au 210 | 220-245-134-144-vic-pppoe.tpgi.com.au 211 | 220-245-144-147.tpgi.com.au 212 | dar-56k-113.tpgi.com.au 213 | sou-ts1-2600-146.tpgi.com.au 214 | ains-202-126-103-14.ains.net.au 215 | cpe-138-130-132-37.nsw.bigpond.net.au 216 | cpe-138-130-15-219.nsw.bigpond.net.au 217 | cpe-138-130-173-1.nsw.bigpond.net.au 218 | cpe-138-130-8-223.nsw.bigpond.net.au 219 | cpe-138-130-90-36.nsw.bigpond.net.au 220 | cpe-141-168-14-244.nsw.bigpond.net.au 221 | cpe-144-132-205-209.nsw.bigpond.net.au 222 | cpe-144-133-115-237.nsw.bigpond.net.au 223 | cpe-144-133-125-203.nsw.bigpond.net.au 224 | cpe-144-137-82-174.nsw.bigpond.net.au 225 | cpe-203-45-119-176.nsw.bigpond.net.au 226 | cpe-203-45-92-93.nsw.bigpond.net.au 227 | cpe-203-45-94-42.nsw.bigpond.net.au 228 | cpe-203-51-90-221.nsw.bigpond.net.au 229 | cpe-203-51-90-240.nsw.bigpond.net.au 230 | cpe-144-136-138-113.qld.bigpond.net.au 231 | cpe-203-45-161-116.qld.bigpond.net.au 232 | cpe-203-45-186-80.qld.bigpond.net.au 233 | cpe-203-45-247-34.qld.bigpond.net.au 234 | cpe-203-45-253-56.qld.bigpond.net.au 235 | cpe-144-137-206-28.sa.bigpond.net.au 236 | cpe-138-217-6-251.vic.bigpond.net.au 237 | cpe-144-132-31-148.vic.bigpond.net.au 238 | cpe-144-132-89-223.vic.bigpond.net.au 239 | cpe-144-136-39-116.vic.bigpond.net.au 240 | cpe-144-136-44-223.vic.bigpond.net.au 241 | cpe-147-10-4-128.vic.bigpond.net.au 242 | cpe-203-45-13-33.vic.bigpond.net.au 243 | cpe-203-45-13-59.vic.bigpond.net.au 244 | cpe-203-45-20-2.vic.bigpond.net.au 245 | cpe-203-45-26-141.vic.bigpond.net.au 246 | cpe-203-45-3-236.vic.bigpond.net.au 247 | cpe-203-45-52-250.vic.bigpond.net.au 248 | cpe-203-45-52-56.vic.bigpond.net.au 249 | cpe-203-45-54-26.vic.bigpond.net.au 250 | cpe-203-45-57-20.vic.bigpond.net.au 251 | cpe-141-168-117-123.wa.bigpond.net.au 252 | ppp-128.cust203-87-114.ghr.chariot.net.au 253 | adsl-172.cust203-87-58.qld.chariot.net.au 254 | 203-206-83-82.dyn.iinet.net.au 255 | 203-217-67-65.dyn.iinet.net.au 256 | 118.a.002.mel.iprimus.net.au 257 | 192.a.004.mel.iprimus.net.au 258 | 132.a.005.mel.iprimus.net.au 259 | 078.b.003.pth.iprimus.net.au 260 | 191.a.002.sop.iprimus.net.au 261 | r220-101-32-36.cpe.unwired.net.au 262 | r220-101-51-168.cpe.unwired.net.au 263 | dial-200.58.187.180.cotas.com.bo 264 | 200191136244-dial-user-ecp.acessonet.com.br 265 | 200191137028-dial-user-ecp.acessonet.com.br 266 | 200-162-218-205.corp.ajato.com.br 267 | 200-162-236-62.corp.ajato.com.br 268 | 200.162.209.101.user.ajato.com.br 269 | 200.162.240.106.user.ajato.com.br 270 | 200.162.226.111.user.ajato.com.br 271 | 200.162.237.151.user.ajato.com.br 272 | 200.162.233.160.user.ajato.com.br 273 | 200.162.248.162.user.ajato.com.br 274 | 200.162.237.184.user.ajato.com.br 275 | 200.162.242.191.user.ajato.com.br 276 | 200-150-186-129.user.ajato.com.br 277 | 200-150-186-146.user.ajato.com.br 278 | 200-170-123-50.user.ajato.com.br 279 | 200.162.225.246.user.ajato.com.br 280 | cm-net-cwb-c8b0318f.brdterra.com.br 281 | cm-net-cwb-c8b032da.brdterra.com.br 282 | cm-net-poa-c8b012fd.brdterra.com.br 283 | cm-tvcidade-rec-c8b14b0c.brdterra.com.br 284 | cm-tvcidade-ssa-c8b1a7d2.brdterra.com.br 285 | cm-virtua-fln-c8b08fef.brdterra.com.br 286 | cm-virtua-poa-c8b0cf9a.brdterra.com.br 287 | net-69-014.cable.cpunet.com.br 288 | 233-134-094.xdsl-dinamico.ctbcnetsuper.com.br 289 | 233-160-025.xdsl-dinamico.ctbcnetsuper.com.br 290 | 233-162-060.xdsl-dinamico.ctbcnetsuper.com.br 291 | 233-162-219.xdsl-dinamico.ctbcnetsuper.com.br 292 | 225-238-082.xdsl-fixo.ctbcnetsuper.com.br 293 | dl-nas8-poa-c89a162f.dialterra.com.br 294 | 200-187-248-101.brt.dialuol.com.br 295 | 200-98-100-214.tlf.dialuol.com.br 296 | 200-98-104-13.tlf.dialuol.com.br 297 | 200-98-34-36.tlf.dialuol.com.br 298 | 200-98-42-24.tlf.dialuol.com.br 299 | 200-98-56-228.tlf.dialuol.com.br 300 | 200-98-90-231.tlf.dialuol.com.br 301 | 200-147-139-241.tlm.dialuol.com.br 302 | 200-147-139-90.tlm.dialuol.com.br 303 | 200-147-50-111.tlm.dialuol.com.br 304 | 200-147-56-34.tlm.dialuol.com.br 305 | 200-147-63-30.tlm.dialuol.com.br 306 | 200-146-180-37.rev.easyband.com.br 307 | max-195-2-59.nwnet.com.br 308 | 200-208-226-202.papalegua.com.br 309 | adsl009c249.sercomtel.com.br 310 | adsl010c062.sercomtel.com.br 311 | adsl011c045.sercomtel.com.br 312 | adsl028c169.sercomtel.com.br 313 | adsl037c142.sercomtel.com.br 314 | adsl041c101.sercomtel.com.br 315 | 200141090077.user.veloxzone.com.br 316 | 200141118124.user.veloxzone.com.br 317 | 200141237250.user.veloxzone.com.br 318 | 200164026195.user.veloxzone.com.br 319 | 200164030128.user.veloxzone.com.br 320 | 200164051123.user.veloxzone.com.br 321 | 200164139135.user.veloxzone.com.br 322 | 200164244039.user.veloxzone.com.br 323 | 200165017149.user.veloxzone.com.br 324 | 200165020086.user.veloxzone.com.br 325 | 200165025091.user.veloxzone.com.br 326 | 200165085049.user.veloxzone.com.br 327 | 200165103194.user.veloxzone.com.br 328 | 200165181005.user.veloxzone.com.br 329 | 200165192141.user.veloxzone.com.br 330 | 200165203097.user.veloxzone.com.br 331 | 200165203183.user.veloxzone.com.br 332 | 200165207241.user.veloxzone.com.br 333 | 200165211136.user.veloxzone.com.br 334 | 200165225067.user.veloxzone.com.br 335 | 200165227253.user.veloxzone.com.br 336 | 200165237002.user.veloxzone.com.br 337 | 200216098185.user.veloxzone.com.br 338 | 200216122136.user.veloxzone.com.br 339 | 200216200048.user.veloxzone.com.br 340 | 201008022127.user.veloxzone.com.br 341 | 201008026250.user.veloxzone.com.br 342 | 201008028015.user.veloxzone.com.br 343 | 201008040176.user.veloxzone.com.br 344 | 201008052192.user.veloxzone.com.br 345 | 201008061141.user.veloxzone.com.br 346 | 201008093034.user.veloxzone.com.br 347 | 201008100159.user.veloxzone.com.br 348 | 201008142162.user.veloxzone.com.br 349 | 201008205051.user.veloxzone.com.br 350 | 201009017015.user.veloxzone.com.br 351 | 201009051176.user.veloxzone.com.br 352 | 201009073074.user.veloxzone.com.br 353 | 201009116225.user.veloxzone.com.br 354 | 201009120103.user.veloxzone.com.br 355 | 201009175111.user.veloxzone.com.br 356 | 201009175118.user.veloxzone.com.br 357 | 201009194232.user.veloxzone.com.br 358 | 201009197039.user.veloxzone.com.br 359 | 201009198135.user.veloxzone.com.br 360 | 201009253081.user.veloxzone.com.br 361 | 201009253186.user.veloxzone.com.br 362 | 201009255037.user.veloxzone.com.br 363 | 99156.virtua.com.br 364 | 233104.bhz.virtua.com.br 365 | 23370.bhz.virtua.com.br 366 | 235136.bhz.virtua.com.br 367 | 235205.bhz.virtua.com.br 368 | 2438.bhz.virtua.com.br 369 | 24513.bhz.virtua.com.br 370 | 2467.bhz.virtua.com.br 371 | 252168.bhz.virtua.com.br 372 | 254154.bhz.virtua.com.br 373 | c8a65a23.bhz.virtua.com.br 374 | c8a65c59.bhz.virtua.com.br 375 | c8a65cf6.bhz.virtua.com.br 376 | c8fbc841.bhz.virtua.com.br 377 | c9060d6a.virtua.com.br 378 | c906127a.virtua.com.br 379 | c9062391.virtua.com.br 380 | c90634c2.virtua.com.br 381 | c9063c5d.virtua.com.br 382 | c90654cd.virtua.com.br 383 | c9065cd8.virtua.com.br 384 | c9066a23.virtua.com.br 385 | c9067080.virtua.com.br 386 | c9068dd8.virtua.com.br 387 | c9069de4.virtua.com.br 388 | c906a41e.virtua.com.br 389 | c906c25f.virtua.com.br 390 | c906d21c.virtua.com.br 391 | c906dc27.virtua.com.br 392 | c906dfdf.virtua.com.br 393 | c906f4cd.virtua.com.br 394 | 16023099.rjo.virtua.com.br 395 | 179231105.rjo.virtua.com.br 396 | 179231167.rjo.virtua.com.br 397 | 179232179.rjo.virtua.com.br 398 | 179235162.rjo.virtua.com.br 399 | 179252126.rjo.virtua.com.br 400 | 179252135.rjo.virtua.com.br 401 | 22349.rjo.virtua.com.br 402 | c9111e57.rjo.virtua.com.br 403 | 44203.soc.virtua.com.br 404 | bhe045156.res-com.wayinternet.com.br 405 | bhe049142.res-com.wayinternet.com.br 406 | 200-203-158-211.mganm202.dial.brasiltelecom.net.br 407 | 200-163-069-170.pmjce204.dial.brasiltelecom.net.br 408 | 200-163-222-060.pnisir201.dial.brasiltelecom.net.br 409 | 200-181-088-098.pvoce205.dial.brasiltelecom.net.br 410 | 200-181-088-219.pvoce205.dial.brasiltelecom.net.br 411 | 200-180-203-206.sance200.dial.brasiltelecom.net.br 412 | 201-002-217-163.bnut37002.dsl.brasiltelecom.net.br 413 | 200-180-079-061.bnut37003.dsl.brasiltelecom.net.br 414 | 200-102-026-056.bnut37004.dsl.brasiltelecom.net.br 415 | 200-101-243-090.bnut37008.dsl.brasiltelecom.net.br 416 | 201-003-254-192.bnut37008.dsl.brasiltelecom.net.br 417 | 201-003-062-073.bsace7031.dsl.brasiltelecom.net.br 418 | 200-103-116-169.bsace704.dsl.brasiltelecom.net.br 419 | 200-140-013-061.bsace705.dsl.brasiltelecom.net.br 420 | 200-140-039-065.cbabm7001.dsl.brasiltelecom.net.br 421 | 200-140-042-237.cbabm7003.dsl.brasiltelecom.net.br 422 | 200-103-007-133.cbabm7004.dsl.brasiltelecom.net.br 423 | 200-096-131-068.cpece7007.dsl.brasiltelecom.net.br 424 | 200-096-131-236.cpece7007.dsl.brasiltelecom.net.br 425 | 200-096-209-080.cpece7007.dsl.brasiltelecom.net.br 426 | 200-203-073-182.cslce7001.dsl.brasiltelecom.net.br 427 | 200-203-075-059.cslce7002.dsl.brasiltelecom.net.br 428 | 200-103-144-122.ctame7014.dsl.brasiltelecom.net.br 429 | 200-103-150-101.ctame7041.dsl.brasiltelecom.net.br 430 | 200-103-131-132.ctame7044.dsl.brasiltelecom.net.br 431 | 200-140-061-027.gnace7003.dsl.brasiltelecom.net.br 432 | 200-140-064-035.gnace7003.dsl.brasiltelecom.net.br 433 | 200-140-066-032.gnace7005.dsl.brasiltelecom.net.br 434 | 200-140-069-073.gnace7005.dsl.brasiltelecom.net.br 435 | 200-101-044-103.gnace7006.dsl.brasiltelecom.net.br 436 | 200-101-044-142.gnace7006.dsl.brasiltelecom.net.br 437 | 200-101-046-032.gnace7006.dsl.brasiltelecom.net.br 438 | 200-103-110-204.gnace7007.dsl.brasiltelecom.net.br 439 | 200-101-241-064.jvece7001.dsl.brasiltelecom.net.br 440 | 200-203-052-062.nhoce7003.dsl.brasiltelecom.net.br 441 | 200-180-161-096.paemt7001.dsl.brasiltelecom.net.br 442 | 200-203-056-030.pltce7001.dsl.brasiltelecom.net.br 443 | 200-101-093-159.pvoce7003.dsl.brasiltelecom.net.br 444 | 200-203-069-095.smace7003.dsl.brasiltelecom.net.br 445 | 200-203-110-185.smace7006.dsl.brasiltelecom.net.br 446 | 200-102-095-016.smace7002.e.brasiltelecom.net.br 447 | 200-161-30-58.dialdata.net.br 448 | 200-171-21-221.dialdata.net.br 449 | 200-171-5-12.dialdata.net.br 450 | 200.175.154.107.dialup.gvt.net.br 451 | 200.175.17.186.dialup.gvt.net.br 452 | 200.175.2.23.dialup.gvt.net.br 453 | 200.175.156.70.tbprof.gvt.net.br 454 | 200-171-228-241.customer.telesp.net.br 455 | 200-100-115-171.dial-up.telesp.net.br 456 | 200-148-37-93.dsl.telesp.net.br 457 | 200-148-40-152.dsl.telesp.net.br 458 | 200-148-64-206.dsl.telesp.net.br 459 | 200-148-7-107.dsl.telesp.net.br 460 | 200-148-9-39.dsl.telesp.net.br 461 | 200-153-131-175.dsl.telesp.net.br 462 | 200-153-145-232.dsl.telesp.net.br 463 | 200-153-156-145.dsl.telesp.net.br 464 | 200-153-192-1.dsl.telesp.net.br 465 | 200-153-192-78.dsl.telesp.net.br 466 | 200-153-209-28.dsl.telesp.net.br 467 | 200-153-222-251.dsl.telesp.net.br 468 | 200-158-124-185.dsl.telesp.net.br 469 | 200-158-138-121.dsl.telesp.net.br 470 | 200-158-149-50.dsl.telesp.net.br 471 | 200-158-174-254.dsl.telesp.net.br 472 | 200-158-184-215.dsl.telesp.net.br 473 | 200-158-191-91.dsl.telesp.net.br 474 | 200-158-199-53.dsl.telesp.net.br 475 | 200-158-2-74.dsl.telesp.net.br 476 | 200-158-211-226.dsl.telesp.net.br 477 | 200-158-23-156.dsl.telesp.net.br 478 | 200-158-42-49.dsl.telesp.net.br 479 | 200-158-5-113.dsl.telesp.net.br 480 | 200-158-74-19.dsl.telesp.net.br 481 | 200-158-79-106.dsl.telesp.net.br 482 | 200-158-99-200.dsl.telesp.net.br 483 | 200-161-1-158.dsl.telesp.net.br 484 | 200-161-223-227.dsl.telesp.net.br 485 | 200-161-55-123.dsl.telesp.net.br 486 | 200-161-62-193.dsl.telesp.net.br 487 | 200-161-73-51.dsl.telesp.net.br 488 | 200-168-111-93.dsl.telesp.net.br 489 | 200-168-132-206.dsl.telesp.net.br 490 | 200-168-132-84.dsl.telesp.net.br 491 | 200-168-132-98.dsl.telesp.net.br 492 | 200-168-142-213.dsl.telesp.net.br 493 | 200-168-142-232.dsl.telesp.net.br 494 | 200-168-44-164.dsl.telesp.net.br 495 | 200-168-68-209.dsl.telesp.net.br 496 | 200-168-78-176.dsl.telesp.net.br 497 | 200-168-93-235.dsl.telesp.net.br 498 | 200-168-95-42.dsl.telesp.net.br 499 | 200-171-119-135.dsl.telesp.net.br 500 | 200-171-13-222.dsl.telesp.net.br 501 | 200-171-139-92.dsl.telesp.net.br 502 | 200-171-170-59.dsl.telesp.net.br 503 | 200-171-173-250.dsl.telesp.net.br 504 | 200-171-42-170.dsl.telesp.net.br 505 | 200-171-42-254.dsl.telesp.net.br 506 | 200-171-78-109.dsl.telesp.net.br 507 | 200-171-99-46.dsl.telesp.net.br 508 | 200-204-122-161.dsl.telesp.net.br 509 | 200-204-150-73.dsl.telesp.net.br 510 | 200-204-152-90.dsl.telesp.net.br 511 | 200-204-154-42.dsl.telesp.net.br 512 | 200-204-181-95.dsl.telesp.net.br 513 | 200-204-197-253.dsl.telesp.net.br 514 | 200-206-150-54.dsl.telesp.net.br 515 | 200-206-184-76.dsl.telesp.net.br 516 | 200-206-195-65.dsl.telesp.net.br 517 | 200-206-217-224.dsl.telesp.net.br 518 | 200-206-237-243.dsl.telesp.net.br 519 | 200-207-115-13.dsl.telesp.net.br 520 | 200-207-129-77.dsl.telesp.net.br 521 | 200-207-144-170.dsl.telesp.net.br 522 | 200-207-145-92.dsl.telesp.net.br 523 | 200-207-162-224.dsl.telesp.net.br 524 | 200-207-164-200.dsl.telesp.net.br 525 | 200-207-166-246.dsl.telesp.net.br 526 | 200-207-38-233.dsl.telesp.net.br 527 | 200-207-4-119.dsl.telesp.net.br 528 | 200-207-54-186.dsl.telesp.net.br 529 | 200-207-97-191.dsl.telesp.net.br 530 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Terms of Perl itself 2 | 3 | a) the GNU General Public License as published by the Free 4 | Software Foundation; either version 1, or (at your option) any 5 | later version, or 6 | b) the "Artistic License" 7 | 8 | ---------------------------------------------------------------------------- 9 | 10 | The General Public License (GPL) 11 | Version 2, June 1991 12 | 13 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 15 | Everyone is permitted to copy and distribute 16 | verbatim copies of this license document, but changing it is not allowed. 17 | 18 | Preamble 19 | 20 | The licenses for most software are designed to take away your freedom to share 21 | and change it. By contrast, the GNU General Public License is intended to 22 | guarantee your freedom to share and change free software--to make sure the 23 | software is free for all its users. This General Public License applies to most of 24 | the Free Software Foundation's software and to any other program whose 25 | authors commit to using it. (Some other Free Software Foundation software is 26 | covered by the GNU Library General Public License instead.) You can apply it to 27 | your programs, too. 28 | 29 | When we speak of free software, we are referring to freedom, not price. Our 30 | General Public Licenses are designed to make sure that you have the freedom 31 | to distribute copies of free software (and charge for this service if you wish), that 32 | you receive source code or can get it if you want it, that you can change the 33 | software or use pieces of it in new free programs; and that you know you can do 34 | these things. 35 | 36 | To protect your rights, we need to make restrictions that forbid anyone to deny 37 | you these rights or to ask you to surrender the rights. These restrictions 38 | translate to certain responsibilities for you if you distribute copies of the 39 | software, or if you modify it. 40 | 41 | For example, if you distribute copies of such a program, whether gratis or for a 42 | fee, you must give the recipients all the rights that you have. You must make 43 | sure that they, too, receive or can get the source code. And you must show 44 | them these terms so they know their rights. 45 | 46 | We protect your rights with two steps: (1) copyright the software, and (2) offer 47 | you this license which gives you legal permission to copy, distribute and/or 48 | modify the software. 49 | 50 | Also, for each author's protection and ours, we want to make certain that 51 | everyone understands that there is no warranty for this free software. If the 52 | software is modified by someone else and passed on, we want its recipients to 53 | know that what they have is not the original, so that any problems introduced by 54 | others will not reflect on the original authors' reputations. 55 | 56 | Finally, any free program is threatened constantly by software patents. We wish 57 | to avoid the danger that redistributors of a free program will individually obtain 58 | patent licenses, in effect making the program proprietary. To prevent this, we 59 | have made it clear that any patent must be licensed for everyone's free use or 60 | not licensed at all. 61 | 62 | The precise terms and conditions for copying, distribution and modification 63 | follow. 64 | 65 | GNU GENERAL PUBLIC LICENSE 66 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND 67 | MODIFICATION 68 | 69 | 0. This License applies to any program or other work which contains a notice 70 | placed by the copyright holder saying it may be distributed under the terms of 71 | this General Public License. The "Program", below, refers to any such program 72 | or work, and a "work based on the Program" means either the Program or any 73 | derivative work under copyright law: that is to say, a work containing the 74 | Program or a portion of it, either verbatim or with modifications and/or translated 75 | into another language. (Hereinafter, translation is included without limitation in 76 | the term "modification".) Each licensee is addressed as "you". 77 | 78 | Activities other than copying, distribution and modification are not covered by 79 | this License; they are outside its scope. The act of running the Program is not 80 | restricted, and the output from the Program is covered only if its contents 81 | constitute a work based on the Program (independent of having been made by 82 | running the Program). Whether that is true depends on what the Program does. 83 | 84 | 1. You may copy and distribute verbatim copies of the Program's source code as 85 | you receive it, in any medium, provided that you conspicuously and appropriately 86 | publish on each copy an appropriate copyright notice and disclaimer of warranty; 87 | keep intact all the notices that refer to this License and to the absence of any 88 | warranty; and give any other recipients of the Program a copy of this License 89 | along with the Program. 90 | 91 | You may charge a fee for the physical act of transferring a copy, and you may at 92 | your option offer warranty protection in exchange for a fee. 93 | 94 | 2. You may modify your copy or copies of the Program or any portion of it, thus 95 | forming a work based on the Program, and copy and distribute such 96 | modifications or work under the terms of Section 1 above, provided that you also 97 | meet all of these conditions: 98 | 99 | a) You must cause the modified files to carry prominent notices stating that you 100 | changed the files and the date of any change. 101 | 102 | b) You must cause any work that you distribute or publish, that in whole or in 103 | part contains or is derived from the Program or any part thereof, to be licensed 104 | as a whole at no charge to all third parties under the terms of this License. 105 | 106 | c) If the modified program normally reads commands interactively when run, you 107 | must cause it, when started running for such interactive use in the most ordinary 108 | way, to print or display an announcement including an appropriate copyright 109 | notice and a notice that there is no warranty (or else, saying that you provide a 110 | warranty) and that users may redistribute the program under these conditions, 111 | and telling the user how to view a copy of this License. (Exception: if the 112 | Program itself is interactive but does not normally print such an announcement, 113 | your work based on the Program is not required to print an announcement.) 114 | 115 | These requirements apply to the modified work as a whole. If identifiable 116 | sections of that work are not derived from the Program, and can be reasonably 117 | considered independent and separate works in themselves, then this License, 118 | and its terms, do not apply to those sections when you distribute them as 119 | separate works. But when you distribute the same sections as part of a whole 120 | which is a work based on the Program, the distribution of the whole must be on 121 | the terms of this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest your rights to 125 | work written entirely by you; rather, the intent is to exercise the right to control 126 | the distribution of derivative or collective works based on the Program. 127 | 128 | In addition, mere aggregation of another work not based on the Program with the 129 | Program (or with a work based on the Program) on a volume of a storage or 130 | distribution medium does not bring the other work under the scope of this 131 | License. 132 | 133 | 3. You may copy and distribute the Program (or a work based on it, under 134 | Section 2) in object code or executable form under the terms of Sections 1 and 2 135 | above provided that you also do one of the following: 136 | 137 | a) Accompany it with the complete corresponding machine-readable source 138 | code, which must be distributed under the terms of Sections 1 and 2 above on a 139 | medium customarily used for software interchange; or, 140 | 141 | b) Accompany it with a written offer, valid for at least three years, to give any 142 | third party, for a charge no more than your cost of physically performing source 143 | distribution, a complete machine-readable copy of the corresponding source 144 | code, to be distributed under the terms of Sections 1 and 2 above on a medium 145 | customarily used for software interchange; or, 146 | 147 | c) Accompany it with the information you received as to the offer to distribute 148 | corresponding source code. (This alternative is allowed only for noncommercial 149 | distribution and only if you received the program in object code or executable 150 | form with such an offer, in accord with Subsection b above.) 151 | 152 | The source code for a work means the preferred form of the work for making 153 | modifications to it. For an executable work, complete source code means all the 154 | source code for all modules it contains, plus any associated interface definition 155 | files, plus the scripts used to control compilation and installation of the 156 | executable. However, as a special exception, the source code distributed need 157 | not include anything that is normally distributed (in either source or binary form) 158 | with the major components (compiler, kernel, and so on) of the operating system 159 | on which the executable runs, unless that component itself accompanies the 160 | executable. 161 | 162 | If distribution of executable or object code is made by offering access to copy 163 | from a designated place, then offering equivalent access to copy the source 164 | code from the same place counts as distribution of the source code, even though 165 | third parties are not compelled to copy the source along with the object code. 166 | 167 | 4. You may not copy, modify, sublicense, or distribute the Program except as 168 | expressly provided under this License. Any attempt otherwise to copy, modify, 169 | sublicense or distribute the Program is void, and will automatically terminate 170 | your rights under this License. However, parties who have received copies, or 171 | rights, from you under this License will not have their licenses terminated so long 172 | as such parties remain in full compliance. 173 | 174 | 5. You are not required to accept this License, since you have not signed it. 175 | However, nothing else grants you permission to modify or distribute the Program 176 | or its derivative works. These actions are prohibited by law if you do not accept 177 | this License. Therefore, by modifying or distributing the Program (or any work 178 | based on the Program), you indicate your acceptance of this License to do so, 179 | and all its terms and conditions for copying, distributing or modifying the 180 | Program or works based on it. 181 | 182 | 6. Each time you redistribute the Program (or any work based on the Program), 183 | the recipient automatically receives a license from the original licensor to copy, 184 | distribute or modify the Program subject to these terms and conditions. You 185 | may not impose any further restrictions on the recipients' exercise of the rights 186 | granted herein. You are not responsible for enforcing compliance by third parties 187 | to this License. 188 | 189 | 7. If, as a consequence of a court judgment or allegation of patent infringement 190 | or for any other reason (not limited to patent issues), conditions are imposed on 191 | you (whether by court order, agreement or otherwise) that contradict the 192 | conditions of this License, they do not excuse you from the conditions of this 193 | License. If you cannot distribute so as to satisfy simultaneously your obligations 194 | under this License and any other pertinent obligations, then as a consequence 195 | you may not distribute the Program at all. For example, if a patent license would 196 | not permit royalty-free redistribution of the Program by all those who receive 197 | copies directly or indirectly through you, then the only way you could satisfy 198 | both it and this License would be to refrain entirely from distribution of the 199 | Program. 200 | 201 | If any portion of this section is held invalid or unenforceable under any particular 202 | circumstance, the balance of the section is intended to apply and the section as 203 | a whole is intended to apply in other circumstances. 204 | 205 | It is not the purpose of this section to induce you to infringe any patents or other 206 | property right claims or to contest validity of any such claims; this section has 207 | the sole purpose of protecting the integrity of the free software distribution 208 | system, which is implemented by public license practices. Many people have 209 | made generous contributions to the wide range of software distributed through 210 | that system in reliance on consistent application of that system; it is up to the 211 | author/donor to decide if he or she is willing to distribute software through any 212 | other system and a licensee cannot impose that choice. 213 | 214 | This section is intended to make thoroughly clear what is believed to be a 215 | consequence of the rest of this License. 216 | 217 | 8. If the distribution and/or use of the Program is restricted in certain countries 218 | either by patents or by copyrighted interfaces, the original copyright holder who 219 | places the Program under this License may add an explicit geographical 220 | distribution limitation excluding those countries, so that distribution is permitted 221 | only in or among countries not thus excluded. In such case, this License 222 | incorporates the limitation as if written in the body of this License. 223 | 224 | 9. The Free Software Foundation may publish revised and/or new versions of the 225 | General Public License from time to time. Such new versions will be similar in 226 | spirit to the present version, but may differ in detail to address new problems or 227 | concerns. 228 | 229 | Each version is given a distinguishing version number. If the Program specifies a 230 | version number of this License which applies to it and "any later version", you 231 | have the option of following the terms and conditions either of that version or of 232 | any later version published by the Free Software Foundation. If the Program does 233 | not specify a version number of this License, you may choose any version ever 234 | published by the Free Software Foundation. 235 | 236 | 10. If you wish to incorporate parts of the Program into other free programs 237 | whose distribution conditions are different, write to the author to ask for 238 | permission. For software which is copyrighted by the Free Software Foundation, 239 | write to the Free Software Foundation; we sometimes make exceptions for this. 240 | Our decision will be guided by the two goals of preserving the free status of all 241 | derivatives of our free software and of promoting the sharing and reuse of 242 | software generally. 243 | 244 | NO WARRANTY 245 | 246 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS 247 | NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 248 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE 249 | COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM 250 | "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR 251 | IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 252 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 253 | ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 254 | PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, 255 | YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 256 | CORRECTION. 257 | 258 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED 259 | TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY 260 | WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS 261 | PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 262 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES 263 | ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 264 | (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 265 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 266 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY 267 | OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 268 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 269 | 270 | END OF TERMS AND CONDITIONS 271 | 272 | 273 | ---------------------------------------------------------------------------- 274 | 275 | The Artistic License 276 | 277 | Preamble 278 | 279 | The intent of this document is to state the conditions under which a Package 280 | may be copied, such that the Copyright Holder maintains some semblance of 281 | artistic control over the development of the package, while giving the users of the 282 | package the right to use and distribute the Package in a more-or-less customary 283 | fashion, plus the right to make reasonable modifications. 284 | 285 | Definitions: 286 | 287 | - "Package" refers to the collection of files distributed by the Copyright 288 | Holder, and derivatives of that collection of files created through textual 289 | modification. 290 | - "Standard Version" refers to such a Package if it has not been modified, 291 | or has been modified in accordance with the wishes of the Copyright 292 | Holder. 293 | - "Copyright Holder" is whoever is named in the copyright or copyrights for 294 | the package. 295 | - "You" is you, if you're thinking about copying or distributing this Package. 296 | - "Reasonable copying fee" is whatever you can justify on the basis of 297 | media cost, duplication charges, time of people involved, and so on. (You 298 | will not be required to justify it to the Copyright Holder, but only to the 299 | computing community at large as a market that must bear the fee.) 300 | - "Freely Available" means that no fee is charged for the item itself, though 301 | there may be fees involved in handling the item. It also means that 302 | recipients of the item may redistribute it under the same conditions they 303 | received it. 304 | 305 | 1. You may make and give away verbatim copies of the source form of the 306 | Standard Version of this Package without restriction, provided that you duplicate 307 | all of the original copyright notices and associated disclaimers. 308 | 309 | 2. You may apply bug fixes, portability fixes and other modifications derived from 310 | the Public Domain or from the Copyright Holder. A Package modified in such a 311 | way shall still be considered the Standard Version. 312 | 313 | 3. You may otherwise modify your copy of this Package in any way, provided 314 | that you insert a prominent notice in each changed file stating how and when 315 | you changed that file, and provided that you do at least ONE of the following: 316 | 317 | a) place your modifications in the Public Domain or otherwise 318 | make them Freely Available, such as by posting said modifications 319 | to Usenet or an equivalent medium, or placing the modifications on 320 | a major archive site such as ftp.uu.net, or by allowing the 321 | Copyright Holder to include your modifications in the Standard 322 | Version of the Package. 323 | 324 | b) use the modified Package only within your corporation or 325 | organization. 326 | 327 | c) rename any non-standard executables so the names do not 328 | conflict with standard executables, which must also be provided, 329 | and provide a separate manual page for each non-standard 330 | executable that clearly documents how it differs from the Standard 331 | Version. 332 | 333 | d) make other distribution arrangements with the Copyright Holder. 334 | 335 | 4. You may distribute the programs of this Package in object code or executable 336 | form, provided that you do at least ONE of the following: 337 | 338 | a) distribute a Standard Version of the executables and library 339 | files, together with instructions (in the manual page or equivalent) 340 | on where to get the Standard Version. 341 | 342 | b) accompany the distribution with the machine-readable source of 343 | the Package with your modifications. 344 | 345 | c) accompany any non-standard executables with their 346 | corresponding Standard Version executables, giving the 347 | non-standard executables non-standard names, and clearly 348 | documenting the differences in manual pages (or equivalent), 349 | together with instructions on where to get the Standard Version. 350 | 351 | d) make other distribution arrangements with the Copyright Holder. 352 | 353 | 5. You may charge a reasonable copying fee for any distribution of this Package. 354 | You may charge any fee you choose for support of this Package. You may not 355 | charge a fee for this Package itself. However, you may distribute this Package in 356 | aggregate with other (possibly commercial) programs as part of a larger 357 | (possibly commercial) software distribution provided that you do not advertise 358 | this Package as a product of your own. 359 | 360 | 6. The scripts and library files supplied as input to or produced as output from 361 | the programs of this Package do not automatically fall under the copyright of this 362 | Package, but belong to whomever generated them, and may be sold 363 | commercially, and may be aggregated with this Package. 364 | 365 | 7. C or perl subroutines supplied by you and linked into this Package shall not 366 | be considered part of this Package. 367 | 368 | 8. The name of the Copyright Holder may not be used to endorse or promote 369 | products derived from this software without specific prior written permission. 370 | 371 | 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR 372 | IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 373 | WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 374 | PURPOSE. 375 | 376 | The End 377 | -------------------------------------------------------------------------------- /Changelog.ini: -------------------------------------------------------------------------------- 1 | [Module] 2 | Name=Regexp::Assemble 3 | Changelog.Creator=Module::Metadata::Changes V 2.12 4 | Changelog.Parser=Config::IniFiles V 3.000001 5 | 6 | [V 0.38] 7 | Date=2017-06-20T08:51:00 8 | Comments= < /a/ 104 | 0.27 2006-11-01 23:43:35 UTC 105 | - rewrote the lexing of patterns in _fastlex(). Unfortunately 106 | this doesn't speed things up as much as I had hoped. 107 | - eg/assemble now recognises -T to dump timing statistics. 108 | - file parameter in add_file() may accept a single scalar 109 | (or a list, as before). 110 | - rs parameter in new() was not recognised as an alias 111 | for input_record_separator, 112 | - anchor_string_absolute as a parameter to new() would not 113 | have worked correctly. 114 | - a couple of anchor_() methods would not have 115 | worked correctly. 116 | - Added MANIFEST.SKIP, now that the module is under 117 | version control. 118 | - Broke out the debug tests into a separate file 119 | (t/09_debug.t). 120 | - cmp_ok() tests that tested equality were replaced by is(). 121 | - tests in t/03_str.t transformed to a data-driven approach, 122 | in order to slim down the size of the distribution tarball. 123 | - Typo spotted in the documentation by Stephan (bug #20425). 124 | 0.26 2006-07-12 09:27:51 UTC 125 | - Incorporated a patch to the test suite from barbie, to work 126 | around a problem encountered on Win32 (bug #17507). 127 | - The "match nothing" pattern was incorrect (but so obscure 128 | as to be reasonably safe). 129 | - Removed the unguarded tests in t/06_general.t that the 130 | Test::More workaround in 0.24 skips. 131 | - Newer versions of Sub::Uplevel no longer need to be guarded 132 | against in t/07_warning.t. 133 | EOT 134 | 135 | [V 0.25] 136 | Date=2006-04-20T18:04:49 137 | Comments= <add( 'a\.b' )->add( 'a-b' )->as_string(indent=>2) 238 | ... would produce a(?:\.|-b) instead of a[-.]b. 239 | - Fixed bug ($ and ^ not treated correctly). See RT ticket 240 | of (?:^|m)a 241 | - Statistics! See the stats_* methods. 242 | - eg/assemble now has an -s switch to display these 243 | statistics 244 | - Minor tweak to t/02_reduce.t to get it to play nicely 245 | with Devel::Cover. 246 | - t/02_reduce.t had an unnecessary use Data::Dumper. 247 | 0.19 2005-11-02 15:16:16 UTC 248 | - Change croaking diagnostic concerning Default_Lexer. 249 | Bug spotted by barbie in ticket #15044. 250 | - Pointer to C in the documentation. 251 | - Excised Test::Deep probe in 00_basic.t, since the 252 | module is no longer used. 253 | - Detabbed eg/* 254 | 0.18 2005-10-08 20:37:53 UTC 255 | - Fixed '\Q[' to be as treated as '\[' instead of '['. 256 | What's more, the tests had this as the Right Thing. 257 | What was I thinking? Wound up rewriting _lex_stateful 258 | in a much less hairier way, even though it now uses 259 | gotos. 260 | - Introduced a context hash for dragging around the bits 261 | and pieces required by the descent into _reduce_path. 262 | It doesn't really help much right now, but is vital for 263 | solving the qw(be by my me) => /[bm][ey]/ problem. See 264 | TODO for more notes. 265 | - Fixed the debug output to play nicely with the test 266 | harness (by prefixing everything with a #). It had never 267 | been a problem, but you never know. 268 | - Added a script named 'debugging' to help people figure 269 | out why assembled patterns go wonky (which is invariably 270 | due to nested parentheses). 271 | - Added a script 'tld', that produces a regexp for 272 | matching internet Top Level Domain names. This happens to 273 | be an ideal example of showing how the alternations are 274 | sorted. 275 | - Added a script 'roman', that produces a regexp for 276 | matching Roman numerals. Just for fun. 277 | - Removed the 'assemble-check' script, whose functionality 278 | is adequately dealt with via 'assemble -t'. 279 | - Tightened up the explanation of why tracked patterns are 280 | bulkier 281 | - ISOfied the dates in this file. 282 | 0.17 2005-09-10 16:41:22 UTC 283 | - Add capture() method. 284 | - Restructure _insert_path(). 285 | - Factor out duplicated code introduced in 0.16 into 286 | _build_re(). 287 | - Ensure that the test suite exercises the fallback 288 | code path for when Storable is missing, even if 289 | Storable is available. 290 | - Added test_pod_coverage, merely to earn a free 291 | Kwalitee point. 292 | 0.16 2005-08-22 23:04:02 UTC 293 | - Tracked patterns silently ignored imsx flags. Spotted by 294 | Bart Lateur. 295 | 0.15 2005-04-27 06:50:31 UTC 296 | - Oops. Detabbed all the files and did not rerun the tests. 297 | t/03_str.t explicitly performs a test on a literal TAB 298 | character, and so it failed. Always, always, *ALWAYS* run 299 | the test suite as the last task before uploading. Grrr. 300 | 0.14 2005-04-27 00:32:43 UTC 301 | - Performance tuning release. Played around significantly 302 | with _insertr and lex but major improvement will only 303 | come about by writing the lexing routine in C. 304 | - Reordered $Default_Lexer to bring the most common cases 305 | to the front of the pattern. 306 | - Inline the effects of \U, \L, \c, \x. This is handled by 307 | _lex_stateful (which offloads some of the worst case 308 | lexing costs into a separate routine and thus makes the 309 | more usual cases run faster). Handling of \Q in the 310 | previous release was incorrect. (Sigh). 311 | - Backslash slashes. 312 | - Passed arrays around by reference between _lex and a 313 | newly introduced _insertr routine. 314 | - Silenced warning in _slide_tail (ran/reran) 315 | - Fixed bug in _slide_tail (didn't handle '0' as a token). 316 | One section of the code used to do its own sliding, now it 317 | uses _slide_tail. 318 | - Fixed bug in _node_eq revealed by 5.6.1 (implicit ordering 319 | of hash keys). 320 | - Optimized node_offset() 321 | - replace ok() in tests by better things (is, like, ...) 322 | - removed use of Test::Differences, since it doesn't work on 323 | complex structures. 324 | 0.13 2005-04-11 21:59:26 UTC 325 | - Deal with \Q...\E patterns. 326 | - $Default_Lexer pattern fails on 5.6.x: it would lex 327 | '\-' as '\', '-'. 328 | - Tests to prove that the global $_ is not clobbered 329 | by the module. 330 | - Used cmp_ok rather than ok where it makes sense. 331 | - Added a (belated) DEBUG_LEX debugging mode 332 | 0.12 2005-04-11 23:49:16 UTC 333 | - Forgot to guard against the possibility of 334 | Test::Differences not being available. This would cause 335 | erroneous failures in the test suite if it was not 336 | installed. 337 | - Quotemeta was still giving troubles. Exhaustive testing 338 | also turned up the fact that a bare add('0') would be 339 | ignored (and thus the null-match pattern would be returned. 340 | - More tweaks to the documentation. 341 | 0.11 Sat Apr 9 19:44:19 2005 UTC 342 | - Performed coverage testing with Devel::Cover 343 | Numerous tests added as a result. Borderline bugs 344 | fixed (bizarre copy of ARRAY in leave under D::C - 345 | fixed in 0.10). 346 | - Finalised the interface to using zero-width lookahead 347 | assertions. Depending on the match/failure ratio of 348 | the pattern to targets, the pattern execution may be 349 | slower with ZWLAs than without. Benchmark it. 350 | - Made _dump call _dump_node if passed a reference to a 351 | hash. This simplifies the code a bit, since one no 352 | longer has to worry about whether the thing we are 353 | looking at is a node or a path. All in all a minor 354 | patch, just to tidy up some loose ends before 355 | moving to heftier optimisations. 356 | - The fix in 0.10 for quotemeta didn't go far enough. 357 | Hopefully this version gets it right. 358 | - A number of minor tweaks based on information 359 | discovered during coverage testing. 360 | - Added documentation about the mailing list. Sundry 361 | documentation tweaks. 362 | 0.10 2005-03-29 09:01:49 UTC 363 | - Correct Default_Lexer$ pattern to deal with the 364 | excessively backslashed tokens that C 365 | likes to produce. Bug spotted by Walter Roberson. 366 | - Added a fix to an obscure bug that Devel::Cover 367 | uncovered. The next release will fold in similar 368 | improvements found by using Devel::Cover. 369 | 0.09 2005-01-22 9:28:21 UTC 370 | - Added lookahead assertions at nodes. (This concept is 371 | shamelessly pinched from Dan Kogai's Regexp::Optimizer). 372 | The code is currently commented out, because in all my 373 | benchmarks the resulting regexps are slower with them. 374 | Look for calls to _combine if you want to play around 375 | with this. 376 | - $Default_Lexer and $Single_Char regexps updated to fix 377 | a bug where backslashed characters were broken apart 378 | between the backslash and the character, resulting in 379 | uncompilable regexps. 380 | - Character classes are now sorted to the left of a list of 381 | alternations. 382 | - Corrected license info in META.yml 383 | - Started to switch from ok() to cmp_ok() in the test suite 384 | to produce human-readable test failures. 385 | 0.08 2005-01-03 11:23:50 UTC 386 | - Bug in insert_node fixed: did not deal with the following 387 | correctly: qw/bcktx bckx bdix bdktx bdkx/ (The assymetry 388 | introduced by 'bdix' threw things off, or something like 389 | that). 390 | - Bug in reduced regexp generation (reinstated code that had 391 | been excised from _re_path() et al). 392 | - Rewrote the tests to eliminate the need for Test::Deep. 393 | Test::More::is_deeply is sufficient. 394 | 0.07 2004-12-17 19:31:18 UTC 395 | - It would have been nice to have remembered to update the 396 | release date in the POD, and the version in the README. 397 | 0.06 2004-12-17 17:38:41 UTC 398 | - Can now track regular expressions. Given a match, it is 399 | possible to determine which original pattern gave rise to the 400 | match. 401 | - Improved character class generation: . (anychar) was not 402 | special-cased, which would have lead to a.b axb giving a[.x]b 403 | Also takes into account single-char width metachars like \t 404 | \e et al. Filters out digits if \d appears, and for similar 405 | metachars (\D, \s, \W...) 406 | - Added a pre_filter method, to perform input filtering prior 407 | to the pattern being lexed. 408 | - Added a flags method, to allow for (?imsx) pattern modifiers. 409 | - enhanced the assemble script: added -b, -c, -d, -v; 410 | documented -r 411 | - Additions to the README 412 | - Added Test::Simple and Test::More as prerequisites. 413 | 0.05 2004-12-10 11:52:13 UTC 414 | - Bug fix in tests. The skip test in version 0.04 did not deal 415 | correctly with non-5.6.0 perls that do not have Test::Deep 416 | installed. 417 | 0.04 2004-12-09 22:29:56 UTC 418 | - In 5.6.0, the backlashes in a quoted word list, qw[ \\d ], 419 | will have their backslashes doubled up. In this case, don't 420 | run the tests. (Reading from a file or getting input from 421 | some other source other than qw[] operators works just fine). 422 | 0.03 2004-12-08 21:55:27 UTC 423 | - Bug fix: Leading 0s could be omitted from paths because of the 424 | difference between while($p) versus while(defined($p)). 425 | - An assembled pattern can be generated with whitespace. This can be 426 | used in conjunction with the /x modifier, and also for debugging. 427 | - Code profiled: dead code paths removed, hotspots rewritten to run 428 | more quickly. 429 | - Documentation typos and wordos. 430 | - assemble script now accepts a number of command line switches to 431 | control its behaviour. 432 | - More tests. Now with Test::Pod. 433 | 0.02 2004-11-19 11:16:33 UTC 434 | - An R::A object that has had nothing added to it now produces a 435 | pattern that explicitly matches nothing (the original behaviour would 436 | match anything). 437 | - An object can now chomp its own input. Useful for slurping files. It 438 | can also filter the input tokens and discard patterns that don't adhere 439 | to what's expected (sanity checking e.g.: don't want spaces). 440 | - Documented and added functions to allow for the lexer pattern to be 441 | manipulated. 442 | - The reset() method was commented out (and the test suite didn't catch 443 | the fact). 444 | - Detabbed the Assemble.pm, eg/* and t/* files (I like interpreting 445 | tabs as four spaces, but this produces horrible indentation on 446 | www.cpan.org). 447 | - t/00_basic.t test counts were wrong. This showed up if Test::Deep was 448 | not installed. 449 | - t/02_reduce.t does not need to 'use Data::Dumper'. 450 | - Tweaked eg/hostmatch/hostmatch; added eg/assemble, eg/assemble-check 451 | - Typos, corrections and addtions to the documentation. 452 | 0.01 2004-07-09 21:05:18 UTC 453 | - original version; created by h2xs 1.19 (seriously!) 454 | EOT 455 | -------------------------------------------------------------------------------- /examples/hostmatch/source.in: -------------------------------------------------------------------------------- 1 | mail.merlin.atlantis.co.ac 2 | smtp4.sms.ac 3 | smtp7.sms.ac 4 | m194-158-65-134.andorpac.ad 5 | m194-158-83-34.andorpac.ad 6 | de11929.alshamil.net.ae 7 | de21057.alshamil.net.ae 8 | de23208.alshamil.net.ae 9 | de2334.alshamil.net.ae 10 | de23392.alshamil.net.ae 11 | de24037.alshamil.net.ae 12 | de24435.alshamil.net.ae 13 | de25655.alshamil.net.ae 14 | domail1.emirates.net.ae 15 | 106-172-89-200.fibertel.com.ar 16 | 106-186-89-200.fibertel.com.ar 17 | 114-196-126-200.fibertel.com.ar 18 | 12-142-126-200.fibertel.com.ar 19 | 140-208-114-200.fibertel.com.ar 20 | 148-148-114-200.fibertel.com.ar 21 | 148-230-114-200.fibertel.com.ar 22 | 188-137-89-200.fibertel.com.ar 23 | 200-155-126-200.fibertel.com.ar 24 | 207-181-89-200.fibertel.com.ar 25 | 224-130-89-200.fibertel.com.ar 26 | 240-196-114-200.fibertel.com.ar 27 | 241-156-114-200.fibertel.com.ar 28 | 241-251-114-200.fibertel.com.ar 29 | 26-159-114-200.fibertel.com.ar 30 | 40-140-126-200.fibertel.com.ar 31 | 5-242-114-200.fibertel.com.ar 32 | 76-191-89-200.fibertel.com.ar 33 | avas-mr09.fibertel.com.ar 34 | avas-mr10.fibertel.com.ar 35 | ol126-12.fibertel.com.ar 36 | ol13-78.fibertel.com.ar 37 | ol134-243.fibertel.com.ar 38 | ol146-22.fibertel.com.ar 39 | ol159-75.fibertel.com.ar 40 | ol169-14.fibertel.com.ar 41 | ol191-125.fibertel.com.ar 42 | ol196-185.fibertel.com.ar 43 | ol199-183.fibertel.com.ar 44 | ol243-132.fibertel.com.ar 45 | ol249-11.fibertel.com.ar 46 | ol249-56.fibertel.com.ar 47 | ol3-37.fibertel.com.ar 48 | ol30-250.fibertel.com.ar 49 | ol55-13.fibertel.com.ar 50 | ol57-192.fibertel.com.ar 51 | ol65-51.fibertel.com.ar 52 | ol68-150.fibertel.com.ar 53 | host13.200.80.24.ifxnw.com.ar 54 | int-200-49-220-42.movi.com.ar 55 | int-200-49-223-245.movi.com.ar 56 | host-239.28.60.66-ta.adsl.netizen.com.ar 57 | cumeil9.prima.com.ar 58 | dsl-200-43-19-83.users.telpin.com.ar 59 | mail.tisa-sistemas.com.ar 60 | 200-112-152-211.bbt.net.ar 61 | 200-122-96-189.prima.net.ar 62 | 200-122-72-230.cab.prima.net.ar 63 | 200-122-72-242.cab.prima.net.ar 64 | 200-122-89-133.cab.prima.net.ar 65 | 200-122-89-187.cab.prima.net.ar 66 | 200-122-90-89.cab.prima.net.ar 67 | 200-42-86-250.cab.prima.net.ar 68 | 200-122-19-254.dsl.prima.net.ar 69 | 200-122-44-246.dsl.prima.net.ar 70 | 200-122-47-219.dsl.prima.net.ar 71 | 200-122-51-48.dsl.prima.net.ar 72 | 200-122-62-222.dsl.prima.net.ar 73 | 200-122-8-86.dsl.prima.net.ar 74 | 200-55-109-42.dsl.prima.net.ar 75 | 200-42-118-237.dup.prima.net.ar 76 | 200-42-27-86.dup.prima.net.ar 77 | 200-42-74-242.wll.prima.net.ar 78 | host3.200-117-255.telecom.net.ar 79 | host161.200-45-119.telecom.net.ar 80 | host9.200-45-119.telecom.net.ar 81 | host52.200-45-154.telecom.net.ar 82 | host10.200-45-234.telecom.net.ar 83 | host135.200-45-236.telecom.net.ar 84 | host53.201-252-211.telecom.net.ar 85 | host52.201-252-215.telecom.net.ar 86 | host23.201-252-89.telecom.net.ar 87 | cabel243b.bkf.at 88 | chello213047046194.1.sc-graz.chello.at 89 | chello080109200248.3.sc-graz.chello.at 90 | viefep11-int.chello.at 91 | viefep12-int.chello.at 92 | viefep15-int.chello.at 93 | viefep18-int.chello.at 94 | viefep19-int.chello.at 95 | 83-64-21-44.dynamic.home.xdsl-line.inode.at 96 | 81-223-84-107.paris-lodron.xdsl-line.inode.at 97 | static81-223-147-187.xdsl-line.inode.at 98 | 83-64-139-186.work.xdsl-line.inode.at 99 | h081217134143.dyn.cm.kabsi.at 100 | h062040180106.med.cm.kabsi.at 101 | h062040175110.moe.cm.kabsi.at 102 | cm101-198.liwest.at 103 | cm105-115.liwest.at 104 | cm127-80.liwest.at 105 | cm130-144.liwest.at 106 | cm133-85.liwest.at 107 | cm144-88.liwest.at 108 | cm152-253.liwest.at 109 | cm156-27.liwest.at 110 | cm176-247.liwest.at 111 | cm220-124.liwest.at 112 | cm238-223.liwest.at 113 | cm239-76.liwest.at 114 | cm240-25.liwest.at 115 | cm249-96.liwest.at 116 | cm62-144.liwest.at 117 | 217-25-113-249.pircher.at 118 | 195-70-102-67.dyn.salzburg-online.at 119 | 195-70-97-81.dyn.salzburg-online.at 120 | 213-153-47-21.dyn.salzburg-online.at 121 | 213-153-48-39.dyn.salzburg-online.at 122 | 82-194-133-193.dyn.salzburg-online.at 123 | 82-194-135-243.dyn.salzburg-online.at 124 | chello213047046108.1.graz.surfer.at 125 | chello080109197149.2.graz.surfer.at 126 | chello080109203248.4.graz.surfer.at 127 | chello080109219252.4.graz.surfer.at 128 | chello213047048050.4.graz.surfer.at 129 | chello084115129099.5.graz.surfer.at 130 | chello080109218197.6.graz.surfer.at 131 | chello212017123151.4.klafu.surfer.at 132 | chello080109132150.tirol.surfer.at 133 | chello080109140115.tirol.surfer.at 134 | chello080109143084.tirol.surfer.at 135 | chello080109164042.tirol.surfer.at 136 | chello062178035093.12.11.vie.surfer.at 137 | chello213047117026.13.11.vie.surfer.at 138 | chello062178052028.18.11.vie.surfer.at 139 | chello080108080045.18.11.vie.surfer.at 140 | chello212017114099.18.11.vie.surfer.at 141 | chello062178054043.19.11.vie.surfer.at 142 | chello212186109127.19.11.vie.surfer.at 143 | chello062178004217.2.11.vie.surfer.at 144 | chello062178059119.20.11.vie.surfer.at 145 | chello080108016046.20.11.vie.surfer.at 146 | chello080108053192.25.11.vie.surfer.at 147 | chello084112028116.25.11.vie.surfer.at 148 | chello062178080107.27.11.vie.surfer.at 149 | chello084112018017.27.11.vie.surfer.at 150 | chello080108036122.31.11.vie.surfer.at 151 | chello212186208124.32.11.vie.surfer.at 152 | chello212186123139.33.11.vie.surfer.at 153 | chello213047134251.33.11.vie.surfer.at 154 | chello212186162128.4.11.vie.surfer.at 155 | chello062178012122.5.11.vie.surfer.at 156 | chello212186105092.6.11.vie.surfer.at 157 | chello080108087243.7.11.vie.surfer.at 158 | chello080108100084.8.11.vie.surfer.at 159 | chello084112006132.8.11.vie.surfer.at 160 | chello062178185143.1.12.vie.surfer.at 161 | chello213047104145.1.12.vie.surfer.at 162 | chello062178230148.10.12.vie.surfer.at 163 | chello084113020081.2.12.vie.surfer.at 164 | chello080108137131.3.12.vie.surfer.at 165 | chello213047105222.3.12.vie.surfer.at 166 | chello080108151071.5.12.vie.surfer.at 167 | chello213047103203.6.12.vie.surfer.at 168 | chello080108168243.9.12.vie.surfer.at 169 | chello080108196048.1.13.vie.surfer.at 170 | chello080108198050.2.13.vie.surfer.at 171 | chello062178125241.3.13.vie.surfer.at 172 | chello080108220235.3.13.vie.surfer.at 173 | chello084113196053.1.14.vie.surfer.at 174 | chello062178164066.11.14.vie.surfer.at 175 | chello080109022046.11.14.vie.surfer.at 176 | chello213047087197.11.14.vie.surfer.at 177 | chello062178165114.12.14.vie.surfer.at 178 | chello084113002037.12.14.vie.surfer.at 179 | chello213047164075.13.14.vie.surfer.at 180 | chello080109053218.14.14.vie.surfer.at 181 | chello062178176224.15.14.vie.surfer.at 182 | chello062178179196.16.14.vie.surfer.at 183 | chello213047061057.2.14.vie.surfer.at 184 | chello212186068249.3.14.vie.surfer.at 185 | chello213047080068.4.14.vie.surfer.at 186 | chello080109092182.15.15.vie.surfer.at 187 | chello080109065078.17.15.vie.surfer.at 188 | chello062178190124.2.15.vie.surfer.at 189 | chello062178231059.3.15.vie.surfer.at 190 | chello080109074169.4.15.vie.surfer.at 191 | chello080109116237.4.15.vie.surfer.at 192 | chello213047128247.15.vie.surfer.at 193 | d213-102-130-44.cust.tele2.at 194 | m097p028.adsl.highway.telekom.at 195 | m1524p010.adsl.highway.telekom.at 196 | m1945p003.adsl.highway.telekom.at 197 | m2236p004.adsl.highway.telekom.at 198 | m369p019.adsl.highway.telekom.at 199 | m763p027.adsl.highway.telekom.at 200 | m898p012.adsl.highway.telekom.at 201 | n219p025.adsl.highway.telekom.at 202 | l1420p29.dipool.highway.telekom.at 203 | chello062178018161.7.11.univie.teleweb.at 204 | chello212017075138.2.15.univie.teleweb.at 205 | chello062178195142.4.15.univie.teleweb.at 206 | chello062178024246.9.11.wu-wien.teleweb.at 207 | cust170.120.nw.tplus.at 208 | dsl-linz7-17-24.utaonline.at 209 | mail1.acnielsen.com.au 210 | dialup-342.syd.ar.com.au 211 | dialup-246.152.220.203.acc01-ball-lis.comindico.com.au 212 | dialup-128.118.221.203.acc02-mcmi-dwn.comindico.com.au 213 | dsl-3.117.240.220.dsl.comindico.com.au 214 | mail.gtlaw.com.au 215 | 210-9-142-38.netspeed.com.au 216 | blaax10-a224.dialup.optusnet.com.au 217 | chtax3-069.dialup.optusnet.com.au 218 | lonax10-b172.dialup.optusnet.com.au 219 | rohax5-023.dialup.optusnet.com.au 220 | wayax5-131.dialup.optusnet.com.au 221 | winax22-179.dialup.optusnet.com.au 222 | wooax17-b154.dialup.optusnet.com.au 223 | d211-29-190-138.dsl.nsw.optusnet.com.au 224 | d211-31-90-216.dsl.nsw.optusnet.com.au 225 | d220-236-28-253.dsl.nsw.optusnet.com.au 226 | c211-28-155-233.eburwd2.vic.optusnet.com.au 227 | c210-49-192-205.lowrp1.vic.optusnet.com.au 228 | 81.fip-213.permisdn.ozemail.com.au 229 | 203-219-27-145-bri-ts4-2600.tpgi.com.au 230 | 220-245-134-144-vic-pppoe.tpgi.com.au 231 | 220-245-144-147.tpgi.com.au 232 | dar-56k-113.tpgi.com.au 233 | sou-ts1-2600-146.tpgi.com.au 234 | orcus.its.uow.edu.au 235 | ains-202-126-103-14.ains.net.au 236 | cpe-138-130-132-37.nsw.bigpond.net.au 237 | cpe-138-130-15-219.nsw.bigpond.net.au 238 | cpe-138-130-173-1.nsw.bigpond.net.au 239 | cpe-138-130-8-223.nsw.bigpond.net.au 240 | cpe-138-130-90-36.nsw.bigpond.net.au 241 | cpe-141-168-14-244.nsw.bigpond.net.au 242 | cpe-144-132-205-209.nsw.bigpond.net.au 243 | cpe-144-133-115-237.nsw.bigpond.net.au 244 | cpe-144-133-125-203.nsw.bigpond.net.au 245 | cpe-144-137-82-174.nsw.bigpond.net.au 246 | cpe-203-45-119-176.nsw.bigpond.net.au 247 | cpe-203-45-92-93.nsw.bigpond.net.au 248 | cpe-203-45-94-42.nsw.bigpond.net.au 249 | cpe-203-51-90-221.nsw.bigpond.net.au 250 | cpe-203-51-90-240.nsw.bigpond.net.au 251 | cpe-144-136-138-113.qld.bigpond.net.au 252 | cpe-203-45-161-116.qld.bigpond.net.au 253 | cpe-203-45-186-80.qld.bigpond.net.au 254 | cpe-203-45-247-34.qld.bigpond.net.au 255 | cpe-203-45-253-56.qld.bigpond.net.au 256 | cpe-144-137-206-28.sa.bigpond.net.au 257 | cpe-138-217-6-251.vic.bigpond.net.au 258 | cpe-144-132-31-148.vic.bigpond.net.au 259 | cpe-144-132-89-223.vic.bigpond.net.au 260 | cpe-144-136-39-116.vic.bigpond.net.au 261 | cpe-144-136-44-223.vic.bigpond.net.au 262 | cpe-147-10-4-128.vic.bigpond.net.au 263 | cpe-203-45-13-33.vic.bigpond.net.au 264 | cpe-203-45-13-59.vic.bigpond.net.au 265 | cpe-203-45-20-2.vic.bigpond.net.au 266 | cpe-203-45-26-141.vic.bigpond.net.au 267 | cpe-203-45-3-236.vic.bigpond.net.au 268 | cpe-203-45-52-250.vic.bigpond.net.au 269 | cpe-203-45-52-56.vic.bigpond.net.au 270 | cpe-203-45-54-26.vic.bigpond.net.au 271 | cpe-203-45-57-20.vic.bigpond.net.au 272 | cpe-141-168-117-123.wa.bigpond.net.au 273 | ppp-128.cust203-87-114.ghr.chariot.net.au 274 | adsl-172.cust203-87-58.qld.chariot.net.au 275 | 203-206-83-82.dyn.iinet.net.au 276 | 203-217-67-65.dyn.iinet.net.au 277 | smtprelay.intellicentre.net.au 278 | 118.a.002.mel.iprimus.net.au 279 | 201.c.002.mel.iprimus.net.au 280 | 192.a.004.mel.iprimus.net.au 281 | 132.a.005.mel.iprimus.net.au 282 | 078.b.003.pth.iprimus.net.au 283 | 191.a.002.sop.iprimus.net.au 284 | smtp02.syd.iprimus.net.au 285 | s089c.static.pacific.net.au 286 | r220-101-32-36.cpe.unwired.net.au 287 | r220-101-51-168.cpe.unwired.net.au 288 | webmail3.onatel.bf 289 | aktor1.adeli.biz 290 | ns1.cheznous.biz 291 | w7.creditland.biz 292 | ns1.gazduire.biz 293 | mail2.hitechpros.biz 294 | relay.link2biz.biz 295 | mx2.wendhlp.biz 296 | mx2.wowie.biz 297 | dial-200.58.187.180.cotas.com.bo 298 | 200191136244-dial-user-ecp.acessonet.com.br 299 | 200191137028-dial-user-ecp.acessonet.com.br 300 | 200-162-218-205.corp.ajato.com.br 301 | 200-162-236-62.corp.ajato.com.br 302 | 200.162.209.101.user.ajato.com.br 303 | 200.162.240.106.user.ajato.com.br 304 | 200.162.226.111.user.ajato.com.br 305 | 200.162.237.151.user.ajato.com.br 306 | 200.162.233.160.user.ajato.com.br 307 | 200.162.248.162.user.ajato.com.br 308 | 200.162.237.184.user.ajato.com.br 309 | 200.162.242.191.user.ajato.com.br 310 | 200-150-186-129.user.ajato.com.br 311 | 200-150-186-146.user.ajato.com.br 312 | 200-170-123-50.user.ajato.com.br 313 | 200.162.225.246.user.ajato.com.br 314 | cm-net-cwb-c8b0318f.brdterra.com.br 315 | cm-net-cwb-c8b032da.brdterra.com.br 316 | cm-net-poa-c8b012fd.brdterra.com.br 317 | cm-tvcidade-rec-c8b14b0c.brdterra.com.br 318 | cm-tvcidade-ssa-c8b1a7d2.brdterra.com.br 319 | cm-virtua-fln-c8b08fef.brdterra.com.br 320 | cm-virtua-poa-c8b0cf9a.brdterra.com.br 321 | mail2.comdominio.com.br 322 | net-69-014.cable.cpunet.com.br 323 | 233-134-094.xdsl-dinamico.ctbcnetsuper.com.br 324 | 233-160-025.xdsl-dinamico.ctbcnetsuper.com.br 325 | 233-162-060.xdsl-dinamico.ctbcnetsuper.com.br 326 | 233-162-219.xdsl-dinamico.ctbcnetsuper.com.br 327 | 225-238-082.xdsl-fixo.ctbcnetsuper.com.br 328 | dl-nas8-poa-c89a162f.dialterra.com.br 329 | 200-187-248-101.brt.dialuol.com.br 330 | 200-98-100-214.tlf.dialuol.com.br 331 | 200-98-104-13.tlf.dialuol.com.br 332 | 200-98-34-36.tlf.dialuol.com.br 333 | 200-98-42-24.tlf.dialuol.com.br 334 | 200-98-56-228.tlf.dialuol.com.br 335 | 200-98-90-231.tlf.dialuol.com.br 336 | 200-147-139-241.tlm.dialuol.com.br 337 | 200-147-139-90.tlm.dialuol.com.br 338 | 200-147-50-111.tlm.dialuol.com.br 339 | 200-147-56-34.tlm.dialuol.com.br 340 | 200-147-63-30.tlm.dialuol.com.br 341 | 200-146-180-37.rev.easyband.com.br 342 | pn41.neoline.com.br 343 | max-195-2-59.nwnet.com.br 344 | 200-208-226-202.papalegua.com.br 345 | adsl009c249.sercomtel.com.br 346 | adsl010c062.sercomtel.com.br 347 | adsl011c045.sercomtel.com.br 348 | adsl028c169.sercomtel.com.br 349 | adsl037c142.sercomtel.com.br 350 | adsl041c101.sercomtel.com.br 351 | sv6.srnet.com.br 352 | cacheflow.sul.com.br 353 | itajuba.terra.com.br 354 | itaparica.terra.com.br 355 | itapoa.terra.com.br 356 | smtpout3.uol.com.br 357 | smtpout6.uol.com.br 358 | web6.vanet.com.br 359 | 200141090077.user.veloxzone.com.br 360 | 200141118124.user.veloxzone.com.br 361 | 200141237250.user.veloxzone.com.br 362 | 200164026195.user.veloxzone.com.br 363 | 200164030128.user.veloxzone.com.br 364 | 200164051123.user.veloxzone.com.br 365 | 200164139135.user.veloxzone.com.br 366 | 200164244039.user.veloxzone.com.br 367 | 200165017149.user.veloxzone.com.br 368 | 200165020086.user.veloxzone.com.br 369 | 200165025091.user.veloxzone.com.br 370 | 200165085049.user.veloxzone.com.br 371 | 200165103194.user.veloxzone.com.br 372 | 200165181005.user.veloxzone.com.br 373 | 200165192141.user.veloxzone.com.br 374 | 200165203097.user.veloxzone.com.br 375 | 200165203183.user.veloxzone.com.br 376 | 200165207241.user.veloxzone.com.br 377 | 200165211136.user.veloxzone.com.br 378 | 200165225067.user.veloxzone.com.br 379 | 200165227253.user.veloxzone.com.br 380 | 200165237002.user.veloxzone.com.br 381 | 200216098185.user.veloxzone.com.br 382 | 200216122136.user.veloxzone.com.br 383 | 200216200048.user.veloxzone.com.br 384 | 201008022127.user.veloxzone.com.br 385 | 201008026250.user.veloxzone.com.br 386 | 201008028015.user.veloxzone.com.br 387 | 201008040176.user.veloxzone.com.br 388 | 201008052192.user.veloxzone.com.br 389 | 201008061141.user.veloxzone.com.br 390 | 201008093034.user.veloxzone.com.br 391 | 201008100159.user.veloxzone.com.br 392 | 201008142162.user.veloxzone.com.br 393 | 201008205051.user.veloxzone.com.br 394 | 201009017015.user.veloxzone.com.br 395 | 201009051176.user.veloxzone.com.br 396 | 201009073074.user.veloxzone.com.br 397 | 201009116225.user.veloxzone.com.br 398 | 201009120103.user.veloxzone.com.br 399 | 201009175111.user.veloxzone.com.br 400 | 201009175118.user.veloxzone.com.br 401 | 201009194232.user.veloxzone.com.br 402 | 201009197039.user.veloxzone.com.br 403 | 201009198135.user.veloxzone.com.br 404 | 201009253081.user.veloxzone.com.br 405 | 201009253186.user.veloxzone.com.br 406 | 201009255037.user.veloxzone.com.br 407 | 99156.virtua.com.br 408 | 233104.bhz.virtua.com.br 409 | 23370.bhz.virtua.com.br 410 | 235136.bhz.virtua.com.br 411 | 235205.bhz.virtua.com.br 412 | 2438.bhz.virtua.com.br 413 | 24513.bhz.virtua.com.br 414 | 2467.bhz.virtua.com.br 415 | 252168.bhz.virtua.com.br 416 | 254154.bhz.virtua.com.br 417 | c8a65a23.bhz.virtua.com.br 418 | c8a65c59.bhz.virtua.com.br 419 | c8a65cf6.bhz.virtua.com.br 420 | c8fbc841.bhz.virtua.com.br 421 | c9060d6a.virtua.com.br 422 | c906127a.virtua.com.br 423 | c9062391.virtua.com.br 424 | c90634c2.virtua.com.br 425 | c9063c5d.virtua.com.br 426 | c90654cd.virtua.com.br 427 | c9065cd8.virtua.com.br 428 | c9066a23.virtua.com.br 429 | c9067080.virtua.com.br 430 | c9068dd8.virtua.com.br 431 | c9069de4.virtua.com.br 432 | c906a41e.virtua.com.br 433 | c906c25f.virtua.com.br 434 | c906d21c.virtua.com.br 435 | c906dc27.virtua.com.br 436 | c906dfdf.virtua.com.br 437 | c906f4cd.virtua.com.br 438 | 16023099.rjo.virtua.com.br 439 | 179231105.rjo.virtua.com.br 440 | 179231167.rjo.virtua.com.br 441 | 179232179.rjo.virtua.com.br 442 | 179235162.rjo.virtua.com.br 443 | 179252126.rjo.virtua.com.br 444 | 179252135.rjo.virtua.com.br 445 | 22349.rjo.virtua.com.br 446 | c9111e57.rjo.virtua.com.br 447 | 44203.soc.virtua.com.br 448 | bhe045156.res-com.wayinternet.com.br 449 | bhe049142.res-com.wayinternet.com.br 450 | ricardo.adm.ita.cta.br 451 | 200-203-158-211.mganm202.dial.brasiltelecom.net.br 452 | 200-163-069-170.pmjce204.dial.brasiltelecom.net.br 453 | 200-163-222-060.pnisir201.dial.brasiltelecom.net.br 454 | 200-181-088-098.pvoce205.dial.brasiltelecom.net.br 455 | 200-181-088-219.pvoce205.dial.brasiltelecom.net.br 456 | 200-180-203-206.sance200.dial.brasiltelecom.net.br 457 | 201-002-217-163.bnut37002.dsl.brasiltelecom.net.br 458 | 200-180-079-061.bnut37003.dsl.brasiltelecom.net.br 459 | 200-102-026-056.bnut37004.dsl.brasiltelecom.net.br 460 | 200-101-243-090.bnut37008.dsl.brasiltelecom.net.br 461 | 201-003-254-192.bnut37008.dsl.brasiltelecom.net.br 462 | 201-003-062-073.bsace7031.dsl.brasiltelecom.net.br 463 | 200-103-116-169.bsace704.dsl.brasiltelecom.net.br 464 | 200-140-013-061.bsace705.dsl.brasiltelecom.net.br 465 | 200-140-039-065.cbabm7001.dsl.brasiltelecom.net.br 466 | 200-140-042-237.cbabm7003.dsl.brasiltelecom.net.br 467 | 200-103-007-133.cbabm7004.dsl.brasiltelecom.net.br 468 | 200-096-131-068.cpece7007.dsl.brasiltelecom.net.br 469 | 200-096-131-236.cpece7007.dsl.brasiltelecom.net.br 470 | 200-096-209-080.cpece7007.dsl.brasiltelecom.net.br 471 | 200-203-073-182.cslce7001.dsl.brasiltelecom.net.br 472 | 200-203-075-059.cslce7002.dsl.brasiltelecom.net.br 473 | 200-103-144-122.ctame7014.dsl.brasiltelecom.net.br 474 | 200-103-150-101.ctame7041.dsl.brasiltelecom.net.br 475 | 200-103-131-132.ctame7044.dsl.brasiltelecom.net.br 476 | 200-140-061-027.gnace7003.dsl.brasiltelecom.net.br 477 | 200-140-064-035.gnace7003.dsl.brasiltelecom.net.br 478 | 200-140-066-032.gnace7005.dsl.brasiltelecom.net.br 479 | 200-140-069-073.gnace7005.dsl.brasiltelecom.net.br 480 | 200-101-044-103.gnace7006.dsl.brasiltelecom.net.br 481 | 200-101-044-142.gnace7006.dsl.brasiltelecom.net.br 482 | 200-101-046-032.gnace7006.dsl.brasiltelecom.net.br 483 | 200-103-110-204.gnace7007.dsl.brasiltelecom.net.br 484 | 200-101-241-064.jvece7001.dsl.brasiltelecom.net.br 485 | 200-203-052-062.nhoce7003.dsl.brasiltelecom.net.br 486 | 200-180-161-096.paemt7001.dsl.brasiltelecom.net.br 487 | 200-203-056-030.pltce7001.dsl.brasiltelecom.net.br 488 | 200-101-093-159.pvoce7003.dsl.brasiltelecom.net.br 489 | 200-203-069-095.smace7003.dsl.brasiltelecom.net.br 490 | 200-203-110-185.smace7006.dsl.brasiltelecom.net.br 491 | 200-102-095-016.smace7002.e.brasiltelecom.net.br 492 | 200-161-30-58.dialdata.net.br 493 | 200-171-21-221.dialdata.net.br 494 | 200-171-5-12.dialdata.net.br 495 | 200.175.154.107.dialup.gvt.net.br 496 | 200.175.17.186.dialup.gvt.net.br 497 | 200.175.2.23.dialup.gvt.net.br 498 | 200.175.156.70.tbprof.gvt.net.br 499 | 200-171-228-241.customer.telesp.net.br 500 | 200-100-115-171.dial-up.telesp.net.br 501 | 200-148-37-93.dsl.telesp.net.br 502 | 200-148-40-152.dsl.telesp.net.br 503 | 200-148-64-206.dsl.telesp.net.br 504 | 200-148-7-107.dsl.telesp.net.br 505 | 200-148-9-39.dsl.telesp.net.br 506 | 200-153-131-175.dsl.telesp.net.br 507 | 200-153-145-232.dsl.telesp.net.br 508 | 200-153-156-145.dsl.telesp.net.br 509 | 200-153-192-1.dsl.telesp.net.br 510 | 200-153-192-78.dsl.telesp.net.br 511 | 200-153-209-28.dsl.telesp.net.br 512 | 200-153-222-251.dsl.telesp.net.br 513 | 200-158-124-185.dsl.telesp.net.br 514 | 200-158-138-121.dsl.telesp.net.br 515 | 200-158-149-50.dsl.telesp.net.br 516 | 200-158-174-254.dsl.telesp.net.br 517 | 200-158-184-215.dsl.telesp.net.br 518 | 200-158-191-91.dsl.telesp.net.br 519 | 200-158-199-53.dsl.telesp.net.br 520 | 200-158-2-74.dsl.telesp.net.br 521 | 200-158-211-226.dsl.telesp.net.br 522 | 200-158-23-156.dsl.telesp.net.br 523 | 200-158-42-49.dsl.telesp.net.br 524 | 200-158-5-113.dsl.telesp.net.br 525 | 200-158-74-19.dsl.telesp.net.br 526 | 200-158-79-106.dsl.telesp.net.br 527 | 200-158-99-200.dsl.telesp.net.br 528 | 200-161-1-158.dsl.telesp.net.br 529 | 200-161-223-227.dsl.telesp.net.br 530 | 200-161-55-123.dsl.telesp.net.br 531 | 200-161-62-193.dsl.telesp.net.br 532 | 200-161-73-51.dsl.telesp.net.br 533 | 200-168-111-93.dsl.telesp.net.br 534 | 200-168-132-206.dsl.telesp.net.br 535 | 200-168-132-84.dsl.telesp.net.br 536 | 200-168-132-98.dsl.telesp.net.br 537 | 200-168-142-213.dsl.telesp.net.br 538 | 200-168-142-232.dsl.telesp.net.br 539 | 200-168-44-164.dsl.telesp.net.br 540 | 200-168-68-209.dsl.telesp.net.br 541 | 200-168-78-176.dsl.telesp.net.br 542 | 200-168-93-235.dsl.telesp.net.br 543 | 200-168-95-42.dsl.telesp.net.br 544 | 200-171-119-135.dsl.telesp.net.br 545 | 200-171-13-222.dsl.telesp.net.br 546 | 200-171-139-92.dsl.telesp.net.br 547 | 200-171-170-59.dsl.telesp.net.br 548 | 200-171-173-250.dsl.telesp.net.br 549 | 200-171-42-170.dsl.telesp.net.br 550 | 200-171-42-254.dsl.telesp.net.br 551 | 200-171-78-109.dsl.telesp.net.br 552 | 200-171-99-46.dsl.telesp.net.br 553 | 200-204-122-161.dsl.telesp.net.br 554 | 200-204-150-73.dsl.telesp.net.br 555 | 200-204-152-90.dsl.telesp.net.br 556 | 200-204-154-42.dsl.telesp.net.br 557 | 200-204-181-95.dsl.telesp.net.br 558 | 200-204-197-253.dsl.telesp.net.br 559 | 200-206-150-54.dsl.telesp.net.br 560 | 200-206-184-76.dsl.telesp.net.br 561 | 200-206-195-65.dsl.telesp.net.br 562 | 200-206-217-224.dsl.telesp.net.br 563 | 200-206-237-243.dsl.telesp.net.br 564 | 200-207-115-13.dsl.telesp.net.br 565 | 200-207-129-77.dsl.telesp.net.br 566 | 200-207-144-170.dsl.telesp.net.br 567 | 200-207-145-92.dsl.telesp.net.br 568 | 200-207-162-224.dsl.telesp.net.br 569 | 200-207-164-200.dsl.telesp.net.br 570 | 200-207-166-246.dsl.telesp.net.br 571 | 200-207-38-233.dsl.telesp.net.br 572 | 200-207-4-119.dsl.telesp.net.br 573 | 200-207-54-186.dsl.telesp.net.br 574 | 200-207-97-191.dsl.telesp.net.br 575 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for Perl extension Regexp::Assemble. 2 | 3 | 0.38 2017-06-20T08:51:00 4 | - Fix test prereqs; pod tests moved to xt (RT#122136, RT#122137) 5 | Many thanx to Karen Etheridge for these patches. 6 | Note: I (Ron) have no idea where the version 2.07 originally comes from, 7 | although I have seen it before. It was not in the very first distro I got 8 | my hands on. Anyway, I've reverted Karen's patch to 0.38 to match the 9 | current sequence of version #s. Apart from that, all these fine 10 | improvements are hers. If this version # causes difficulties, I'll just 11 | bump it to 2.08. 12 | - Adopt new repo structure. For details, see 13 | http://savage.net.au/Ron/html/My.Workflow.for.Building.Distros.html. 14 | Specifically: 15 | o Delete MANIFEST and META.yml, and hereafter auto-generate them. 16 | o Modernize .gitignore and MANIFEST.SKIP. 17 | o The code says Perl licence but the LICENCE file says Artistic, so 18 | replace LICENCE file with LICENSE (so spelled), which says Perl. 19 | 20 | 0.37 2016-04-18T08:51:00 21 | - No code changes. 22 | - Accept pull request from monsieurp to add a LICENCE (sic, see below) 23 | file. With thanx. This activity is part of the CPAN PR Challenge 2016. 24 | - Update MANIFEST to include LICENCE file. 25 | - Remove unicode characters from Changes and Changelog.ini files. 26 | - Add TODO and update MANIFEST to note unicode issues. 27 | - Add .gitignore to MANIFEST.SKIP. 28 | 29 | 0.36 2015-08-16T11:34:00 30 | - Ron Savage is now co-maint. 31 | - Move eg/ to examples/. 32 | - Many thanx to the various parties who logged issues on RT. Some have been 33 | fixed, see below. 34 | - Add examples/failure.01.pl, downloaded, and noted in docs, from 35 | https://rt.cpan.org/Public/Bug/Display.html?id=104897 36 | - Move pod tests into xt/author/pod.t by cutting them out of t/00_basic.t. 37 | See https://rt.cpan.org/Public/Bug/Display.html?id=85686 38 | and https://rt.cpan.org/Public/Bug/Display.html?id=85209 39 | - Add repository https://github.com/ronsavage/Regexp-Assemble.git. 40 | Note: github does not list Perl as one of the licence options, so the 41 | auto-generated LICENSE (sic) file is not included in the distro. 42 | See https://rt.cpan.org/Public/Bug/Display.html?id=103856. 43 | - Fix some spelling errors in the pod. 44 | See https://rt.cpan.org/Public/Bug/Display.html?id=84336 45 | - Move ./Assemble.pm into lib/Regexp/. 46 | - Move the contents of the TODO file into the docs, and delete that file. 47 | - Rearrange pod, but not be running this module over it :-). Actually, put 48 | pod at end of file. 49 | - Update Makefile.PL. 50 | - Add Changelog.ini. 51 | - Update MANIFEST.SKIP. 52 | 53 | 0.35 2011-04-07 13:18:48 UTC 54 | - Update test suite to take into account the regexp 55 | engine changes for 5.14. No functional differences. 56 | 57 | 0.34 2008-06-17 20:20:14 UTC 58 | - Rewrite the usage of _re_sort() in order to deal 59 | with blead change #33874. Bug smoked out by Andreas 60 | Konig. 61 | 62 | 0.33 2008-06-07 14:40:57 UTC 63 | - Tweaked _fastlex() to fix bug #36399 spotted by Yves 64 | Blusseau ('a|[bc]' becomes 'a\|[bc]'). 65 | - Recognise POSIX character classes (e.g. [[:alpha:]]. 66 | Bug also spotted by Yves Blusseau (bug #36465). 67 | 68 | 0.32 2007-07-30 17:47:39 UTC 69 | - Backed out the change introduced in 0.25 (that created 70 | slimmer regexps when custom flags are used). As things 71 | stood, it meant that '/' could not appear in a pattern 72 | with flags (and could possibly dump core). Bug #28554 73 | noted by David Morel. 74 | - Allow a+b to be unrolled into aa*b, as that may allow 75 | further reductions (bug #20847 noted by Philippe Bruhat). 76 | Not completely implemented, but bug #28554 is sufficient 77 | to push out a new release. 78 | - eg/assemble understands -U to enable plus unrollings. 79 | - Extended campaign of coverage improvements made to the 80 | test suite caught a minor flaw in source(). 81 | 82 | 0.31 2007-06-04 20:40:33 UTC 83 | - Add a fold_meta_pairs flag to control the behaviour of 84 | [\S\s] (and [\D\d], [\W\w]) being folded to '.' (bug 85 | #24171 spotted by Philippe Bruhat). 86 | 87 | 0.30 2007-05-18 15:39:37 UTC 88 | - Fixup _fastlex() bug in 5.6 (unable to discriminate \cX). 89 | This allows bug #27138 to be closed. 90 | 91 | 0.29 2007-05-17 10:48:42 UTC 92 | - Tracked patterns enhanced to take advantage of 5.10 93 | (and works again with blead). 94 | - The mutable() functionality has been marked as 95 | deprecated. 96 | - mailing list web page was incorrect (noted by Kai 97 | Carver) 98 | 99 | 0.28 2006-11-26 21:49:26 UTC 100 | - Fixed a.+ bug (interpreted as a\.+) (bug #23623) 101 | - Handle /[a]/ => /a/ 102 | 103 | 0.27 2006-11-01 23:43:35 UTC 104 | - rewrote the lexing of patterns in _fastlex(). Unfortunately 105 | this doesn't speed things up as much as I had hoped. 106 | - eg/assemble now recognises -T to dump timing statistics. 107 | - file parameter in add_file() may accept a single scalar 108 | (or a list, as before). 109 | - rs parameter in new() was not recognised as an alias 110 | for input_record_separator, 111 | - anchor_string_absolute as a parameter to new() would not 112 | have worked correctly. 113 | - a couple of anchor_() methods would not have 114 | worked correctly. 115 | - Added MANIFEST.SKIP, now that the module is under 116 | version control. 117 | - Broke out the debug tests into a separate file 118 | (t/09_debug.t). 119 | - cmp_ok() tests that tested equality were replaced by is(). 120 | - tests in t/03_str.t transformed to a data-driven approach, 121 | in order to slim down the size of the distribution tarball. 122 | - Typo spotted in the documentation by Stephan (bug #20425). 123 | 124 | 0.26 2006-07-12 09:27:51 UTC 125 | - Incorporated a patch to the test suite from barbie, to work 126 | around a problem encountered on Win32 (bug #17507). 127 | - The "match nothing" pattern was incorrect (but so obscure 128 | as to be reasonably safe). 129 | - Removed the unguarded tests in t/06_general.t that the 130 | Test::More workaround in 0.24 skips. 131 | - Newer versions of Sub::Uplevel no longer need to be guarded 132 | against in t/07_warning.t. 133 | 134 | 0.25 2006-04-20 18:04:49 135 | - Added a debug switch to elapsed pattern insertion and 136 | pattern reduction times. Upgraded eg/assemble to make 137 | use of it. 138 | - Tweaked the resulting pattern when it uses 'imsx' 139 | flags, giving (?i-xsm:(?:^a[bc]|de)) instead of 140 | (?-xism:(?i:(?:^a[bc]|de))) . 141 | - Changed the "match nothing" pattern to something slightly 142 | less unsurprising to those who peek behind the curtain. 143 | Reported by Philippe Bruhat (bug #18266). 144 | - Tweaked the dump() output for chars \x00 .. \x1f 145 | 146 | 0.24 2006-03-21 08:50:42 147 | - Added an add_file() method that allows a file of patterns to 148 | be slurped into an object. Makes for less make-work code in 149 | the client code (and thus one less thing to go wrong there). 150 | - Added anchor methods that tack on \b, ^, $ and the like to an 151 | assembled pattern. 152 | - Rewrote new() and clone(). The latter is now no longer needs 153 | to know the attribute names. 154 | - _lex_stateful() subsumed into _lex() 155 | - \d and \w assemble to \w instead of [\w\d] (and similarly for 156 | \D and \W). 157 | - The Test::More workaround stated in the 0.23 changes didn't 158 | actually make it into t/06_general.t 159 | - Rewrote tests in 06_general.t to use like()/unlike() instead 160 | of ok(), and some more ok()'s replaced by cmp_ok() 161 | elsewhere. 162 | - Diagnostics for t/00_basic.t:xcmp was incorrect (displayed 163 | first param instead of second). 164 | - Guard against broken Sub::Uplevel in t/07_warning.t for 165 | perl 5.8.8. 166 | - Pretty-print characters [\x00-\x1f] in _dump() routines. 167 | - Spell-checked the POD! 168 | 169 | 0.23 2006-01-03 17:03:35 170 | - More bugs in the reduction code shaken out by examining 171 | powersets. Exhaustive testing (iterating through the 172 | powerset of a, b, c, d, e) makes me think that the 173 | pathological cases are taken care of. The code is horrible, 174 | though, a rewrite is next on the agenda. 175 | - Guard against earlier buggy versions of Test::More (0.47) 176 | in t/06_general.t 177 | - Carp::croak rewritten as Carp::croak() to fix failures 178 | noted on blead. 179 | - Rewrote _re_path() for speed. 180 | - added lexstr() routine. 181 | - added eg/stress-test program. 182 | 183 | 0.22 2005-12-02 11:31:42 UTC 184 | - Amended the test suite to ensure that it runsh0orrectly under 185 | 5.005_04. (The documentation was updated to reflect the 186 | limitations). Sbastien Aperghis-Tramoni provided the impetus 187 | for this fix. No other changes in functionality. 188 | - The SKIP counts in t/06_general.t were out of whack for 5.6 189 | and 5.005 testing. 190 | 191 | 0.21 2005-11-26 16:16:06 UTC 192 | - Fixed a nasty bug after generating a series of lists of 193 | patterns using Data::PowerSet: ^abc$ ^abcd$ ^ac$ ^acd$ ^b$ 194 | ^bc$ ^bcd$ ^bd$ would produce the incorrect 195 | ^b(?:(?:ab?)?c)?d?$ pattern. It should if fact produce the 196 | ^(?:ab?c|bc?)d?$ pattern. 197 | - Improve the reduction of, for example, 'sing', 'singing', 198 | 'sting'. In prior versions this would produce 199 | s(?:ing(?:ing)?|ting), now it produces s(?:(?:ing)?|t)ing. 200 | The code is a bit horrendous (especially the part at the end 201 | of _reduce_path). And it's still not perfect. See the TODO. 202 | - Duplicate pattern detection wasn't quite right. The code 203 | was lacking an else clause, which meant 'abcdef' followed by 204 | 'abc' would have the latter treated as a duplicate. 205 | - Now that there's a statistic that keeps track of when a 206 | duplicate input pattern was encountered, it becomes possible 207 | to let the user know about it. Two possibilities are available: 208 | a simple carp(), or a callback for complete control. The first 209 | time I tried this out on a real file of 3558 patterns, it found 210 | 9 dups (or rather, 8 dups and a bug in the module). 211 | - The above improvement means the test suite now requires 212 | Test::Warn. As a result, t/07_pod.t was subsumed into 213 | t/00_basic.t and t/07_warning.t was born. 214 | - Added an eg/ircwatcher script that demonstrates how to set up a 215 | dispatch table on a tracked regular expression. Credit to David 216 | Rigaudiere for the idea. 217 | - Made sure all routines use an explicit return when it makes 218 | sense to do so. (I have a tendency to use implicit returns, 219 | which is evil). 220 | - the Carp module is require'ed on an on-demand basis. 221 | - eg/naive updated to bring its idea of $Single_Char in line with 222 | Assemble.pm. 223 | - Cleaned up typos and PODos in the documentation. Fixed minor 224 | typo noted by David Rigaudiere. 225 | - Reworked as_string() and re() to play nicely with Devel::Cover, 226 | but alas, the module no longer runs under D::C at all. Something 227 | to do with the overloading of "" for re()? 228 | 229 | 0.20 2005-11-07 18:03:32 UTC 230 | - Fixed long-standing indent bug: 231 | $ra->add( 'a\.b' )->add( 'a-b' )->as_string(indent=>2) 232 | ... would produce a(?:\.|-b) instead of a[-.]b. 233 | - Fixed bug ($ and ^ not treated correctly). See RT ticket 234 | #15522. Basically, '^a' and 'ma' produced [m^]a instead 235 | of (?:^|m)a 236 | - Statistics! See the stats_* methods. 237 | - eg/assemble now has an -s switch to display these 238 | statistics 239 | - Minor tweak to t/02_reduce.t to get it to play nicely 240 | with Devel::Cover. 241 | - t/02_reduce.t had an unnecessary use Data::Dumper. 242 | 243 | 0.19 2005-11-02 15:16:16 UTC 244 | - Change croaking diagnostic concerning Default_Lexer. 245 | Bug spotted by barbie in ticket #15044. 246 | - Pointer to C in the documentation. 247 | - Excised Test::Deep probe in 00_basic.t, since the 248 | module is no longer used. 249 | - Detabbed eg/* 250 | 251 | 0.18 2005-10-08 20:37:53 UTC 252 | - Fixed '\Q[' to be as treated as '\[' instead of '['. 253 | What's more, the tests had this as the Right Thing. 254 | What was I thinking? Wound up rewriting _lex_stateful 255 | in a much less hairier way, even though it now uses 256 | gotos. 257 | - Introduced a context hash for dragging around the bits 258 | and pieces required by the descent into _reduce_path. 259 | It doesn't really help much right now, but is vital for 260 | solving the qw(be by my me) => /[bm][ey]/ problem. See 261 | TODO for more notes. 262 | - Fixed the debug output to play nicely with the test 263 | harness (by prefixing everything with a #). It had never 264 | been a problem, but you never know. 265 | - Added a script named 'debugging' to help people figure 266 | out why assembled patterns go wonky (which is invariably 267 | due to nested parentheses). 268 | - Added a script 'tld', that produces a regexp for 269 | matching internet Top Level Domain names. This happens to 270 | be an ideal example of showing how the alternations are 271 | sorted. 272 | - Added a script 'roman', that produces a regexp for 273 | matching Roman numerals. Just for fun. 274 | - Removed the 'assemble-check' script, whose functionality 275 | is adequately dealt with via 'assemble -t'. 276 | - Tightened up the explanation of why tracked patterns are 277 | bulkier 278 | - ISOfied the dates in this file. 279 | 280 | 0.17 2005-09-10 16:41:22 UTC 281 | - Add capture() method. 282 | - Restructure _insert_path(). 283 | - Factor out duplicated code introduced in 0.16 into 284 | _build_re(). 285 | - Ensure that the test suite exercises the fallback 286 | code path for when Storable is missing, even if 287 | Storable is available. 288 | - Added test_pod_coverage, merely to earn a free 289 | Kwalitee point. 290 | 291 | 0.16 2005-08-22 23:04:02 UTC 292 | - Tracked patterns silently ignored imsx flags. Spotted by 293 | Bart Lateur. 294 | 295 | 0.15 2005-04-27 06:50:31 UTC 296 | - Oops. Detabbed all the files and did not rerun the tests. 297 | t/03_str.t explicitly performs a test on a literal TAB 298 | character, and so it failed. Always, always, *ALWAYS* run 299 | the test suite as the last task before uploading. Grrr. 300 | 301 | 0.14 2005-04-27 00:32:43 UTC 302 | - Performance tuning release. Played around significantly 303 | with _insertr and lex but major improvement will only 304 | come about by writing the lexing routine in C. 305 | - Reordered $Default_Lexer to bring the most common cases 306 | to the front of the pattern. 307 | - Inline the effects of \U, \L, \c, \x. This is handled by 308 | _lex_stateful (which offloads some of the worst case 309 | lexing costs into a separate routine and thus makes the 310 | more usual cases run faster). Handling of \Q in the 311 | previous release was incorrect. (Sigh). 312 | - Backslash slashes. 313 | - Passed arrays around by reference between _lex and a 314 | newly introduced _insertr routine. 315 | - Silenced warning in _slide_tail (ran/reran) 316 | - Fixed bug in _slide_tail (didn't handle '0' as a token). 317 | One section of the code used to do its own sliding, now it 318 | uses _slide_tail. 319 | - Fixed bug in _node_eq revealed by 5.6.1 (implicit ordering 320 | of hash keys). 321 | - Optimized node_offset() 322 | - replace ok() in tests by better things (is, like, ...) 323 | - removed use of Test::Differences, since it doesn't work on 324 | complex structures. 325 | 326 | 0.13 2005-04-11 21:59:26 UTC 327 | - Deal with \Q...\E patterns. 328 | - $Default_Lexer pattern fails on 5.6.x: it would lex 329 | '\-' as '\', '-'. 330 | - Tests to prove that the global $_ is not clobbered 331 | by the module. 332 | - Used cmp_ok rather than ok where it makes sense. 333 | - Added a (belated) DEBUG_LEX debugging mode 334 | 335 | 0.12 2005-04-11 23:49:16 UTC 336 | - Forgot to guard against the possibility of 337 | Test::Differences not being available. This would cause 338 | erroneous failures in the test suite if it was not 339 | installed. 340 | - Quotemeta was still giving troubles. Exhaustive testing 341 | also turned up the fact that a bare add('0') would be 342 | ignored (and thus the null-match pattern would be returned. 343 | - More tweaks to the documentation. 344 | 345 | 0.11 Sat Apr 9 19:44:19 2005 UTC 346 | - Performed coverage testing with Devel::Cover 347 | Numerous tests added as a result. Borderline bugs 348 | fixed (bizarre copy of ARRAY in leave under D::C - 349 | fixed in 0.10). 350 | - Finalised the interface to using zero-width lookahead 351 | assertions. Depending on the match/failure ratio of 352 | the pattern to targets, the pattern execution may be 353 | slower with ZWLAs than without. Benchmark it. 354 | - Made _dump call _dump_node if passed a reference to a 355 | hash. This simplifies the code a bit, since one no 356 | longer has to worry about whether the thing we are 357 | looking at is a node or a path. All in all a minor 358 | patch, just to tidy up some loose ends before 359 | moving to heftier optimisations. 360 | - The fix in 0.10 for quotemeta didn't go far enough. 361 | Hopefully this version gets it right. 362 | - A number of minor tweaks based on information 363 | discovered during coverage testing. 364 | - Added documentation about the mailing list. Sundry 365 | documentation tweaks. 366 | 367 | 0.10 2005-03-29 09:01:49 UTC 368 | - Correct Default_Lexer$ pattern to deal with the 369 | excessively backslashed tokens that C 370 | likes to produce. Bug spotted by Walter Roberson. 371 | - Added a fix to an obscure bug that Devel::Cover 372 | uncovered. The next release will fold in similar 373 | improvements found by using Devel::Cover. 374 | 375 | 0.09 2005-01-22 9:28:21 UTC 376 | - Added lookahead assertions at nodes. (This concept is 377 | shamelessly pinched from Dan Kogai's Regexp::Optimizer). 378 | The code is currently commented out, because in all my 379 | benchmarks the resulting regexps are slower with them. 380 | Look for calls to _combine if you want to play around 381 | with this. 382 | - $Default_Lexer and $Single_Char regexps updated to fix 383 | a bug where backslashed characters were broken apart 384 | between the backslash and the character, resulting in 385 | uncompilable regexps. 386 | - Character classes are now sorted to the left of a list of 387 | alternations. 388 | - Corrected license info in META.yml 389 | - Started to switch from ok() to cmp_ok() in the test suite 390 | to produce human-readable test failures. 391 | 392 | 0.08 2005-01-03 11:23:50 UTC 393 | - Bug in insert_node fixed: did not deal with the following 394 | correctly: qw/bcktx bckx bdix bdktx bdkx/ (The assymetry 395 | introduced by 'bdix' threw things off, or something like 396 | that). 397 | - Bug in reduced regexp generation (reinstated code that had 398 | been excised from _re_path() et al). 399 | - Rewrote the tests to eliminate the need for Test::Deep. 400 | Test::More::is_deeply is sufficient. 401 | 402 | 0.07 2004-12-17 19:31:18 UTC 403 | - It would have been nice to have remembered to update the 404 | release date in the POD, and the version in the README. 405 | 406 | 0.06 2004-12-17 17:38:41 UTC 407 | - Can now track regular expressions. Given a match, it is 408 | possible to determine which original pattern gave rise to the 409 | match. 410 | - Improved character class generation: . (anychar) was not 411 | special-cased, which would have lead to a.b axb giving a[.x]b 412 | Also takes into account single-char width metachars like \t 413 | \e et al. Filters out digits if \d appears, and for similar 414 | metachars (\D, \s, \W...) 415 | - Added a pre_filter method, to perform input filtering prior 416 | to the pattern being lexed. 417 | - Added a flags method, to allow for (?imsx) pattern modifiers. 418 | - enhanced the assemble script: added -b, -c, -d, -v; 419 | documented -r 420 | - Additions to the README 421 | - Added Test::Simple and Test::More as prerequisites. 422 | 423 | 0.05 2004-12-10 11:52:13 UTC 424 | - Bug fix in tests. The skip test in version 0.04 did not deal 425 | correctly with non-5.6.0 perls that do not have Test::Deep 426 | installed. 427 | 428 | 0.04 2004-12-09 22:29:56 UTC 429 | - In 5.6.0, the backlashes in a quoted word list, qw[ \\d ], 430 | will have their backslashes doubled up. In this case, don't 431 | run the tests. (Reading from a file or getting input from 432 | some other source other than qw[] operators works just fine). 433 | 434 | 0.03 2004-12-08 21:55:27 UTC 435 | - Bug fix: Leading 0s could be omitted from paths because of the 436 | difference between while($p) versus while(defined($p)). 437 | - An assembled pattern can be generated with whitespace. This can be 438 | used in conjunction with the /x modifier, and also for debugging. 439 | - Code profiled: dead code paths removed, hotspots rewritten to run 440 | more quickly. 441 | - Documentation typos and wordos. 442 | - assemble script now accepts a number of command line switches to 443 | control its behaviour. 444 | - More tests. Now with Test::Pod. 445 | 446 | 0.02 2004-11-19 11:16:33 UTC 447 | - An R::A object that has had nothing added to it now produces a 448 | pattern that explicitly matches nothing (the original behaviour would 449 | match anything). 450 | - An object can now chomp its own input. Useful for slurping files. It 451 | can also filter the input tokens and discard patterns that don't adhere 452 | to what's expected (sanity checking e.g.: don't want spaces). 453 | - Documented and added functions to allow for the lexer pattern to be 454 | manipulated. 455 | - The reset() method was commented out (and the test suite didn't catch 456 | the fact). 457 | - Detabbed the Assemble.pm, eg/* and t/* files (I like interpreting 458 | tabs as four spaces, but this produces horrible indentation on 459 | www.cpan.org). 460 | - t/00_basic.t test counts were wrong. This showed up if Test::Deep was 461 | not installed. 462 | - t/02_reduce.t does not need to 'use Data::Dumper'. 463 | - Tweaked eg/hostmatch/hostmatch; added eg/assemble, eg/assemble-check 464 | - Typos, corrections and addtions to the documentation. 465 | 466 | 0.01 2004-07-09 21:05:18 UTC 467 | - original version; created by h2xs 1.19 (seriously!) 468 | --------------------------------------------------------------------------------