2011-01-04 10 views
6

Z man perlre: ""perlre długość granica

przycisk "*" kwantyfikator jest równoważne "{0}", znak "+" do kwantyfikatora "{1}" i kwantyfikator do "{0,1}". Wartości n i m są ograniczone do wartości integralnych mniejszych od ustalonego limitu zdefiniowanego podczas budowania perla. Zazwyczaj jest to 32766 na najpopularniejszych platformach. Rzeczywista granica może być postrzegane w komunikacie o błędzie wygenerowanym kodem takich jak to:

 $_ **= $_ ,/{$_}/for 2 .. 42; 

Ay, że jest brzydka - nie jest jakiś stały mogę zamiast tego?

Edytuj: Jak zauważył daxim (i perlretut wskazówki) może być tak, że 32767 jest magiczną, zakodowaną na stałe liczbą. Trochę searching w kodzie Perl przechodzi długą drogę, ale nie jestem pewien, w jaki sposób dostać się do następnego etapu i rzeczywiście dowiedzieć się, gdzie domyślnym reg_infty lub REG_INFTY jest właściwie ustawiony:

~/dev/perl-5.12.2 
$ grep -ri 'reg_infty.*=' * 
regexec.c:  if (max != REG_INFTY && ST.count == max) 
t/re/pat.t:  $::reg_infty = $Config {reg_infty} // 32767; 
t/re/pat.t:  $::reg_infty_m = $::reg_infty - 1; 
t/re/pat.t:  $::reg_infty_p = $::reg_infty + 1; 
t/re/pat.t:  $::reg_infty_m = $::reg_infty_m; # Surpress warning. 

Edit 2: DVK ma oczywiście rację: jest to define d w czasie kompilacji i prawdopodobnie można go zastąpić tylko REG_INFTY.

+5

także zobaczyć http://perl.plover.com/yak/regex/samples/slide050.html – daxim

+0

@daxim: myślę masz tam pełną odpowiedź, a nie tylko komentarz. "Nawet gdybyś znał limit, nie byłby to przydatny numer, ponieważ silnik regex prawdopodobnie umrze, zanim osiągnie teoretyczny limit". –

Odpowiedz

8

Podsumowanie: istnieją 3 sposoby, w jakie mogę znaleźć ograniczenie: empiryczne, "dopasowanie testów Perla" i "teoretyczne".

  • empiryczne:

    eval {$_ **= $_ ,/{$_}/for 2 .. 129}; 
    # To be truly portable, the above should ideally loop forever till [email protected] is true. 
    [email protected] =~ /bigger than (-?\d+) /; 
    print "LIMIT: $1\n"' 
    

    To wydaje się dość oczywiste, że nie wymaga wyjaśnień.

  • zestawienia testuje Perl

    Perl posiada szereg badań dla wyrażenia regularnego, a niektóre z nich (w pat.t) zajmują badania z maksymalnej wartości. Tak, można w przybliżeniu, że wartość max obliczane w tych badaniach jest „wystarczająco dobre” i postępuj zgodnie z logiką testu,:

    use Config; 
    $reg_infty = $Config {reg_infty} // 2 ** 15 - 1; # 32767 
    print "Test-based reg_infinity limit: $reg_infty\n"; 
    

    Wyjaśnienie gdzie w testach ten jest oparty off jest w poniższych informacji.

  • Teoretyczne: Próbuje replikować logikę EXACT używaną przez kod C w celu wygenerowania tej wartości.

    To jest trudniejsze, niż się wydaje, ponieważ ma wpływ na 2 rzeczy: konfigurację kompilacji Perla i kilka instrukcji C #define z logiką rozgałęzienia. Byłem w stanie dość głęboko zagłębić się w tę logikę, ale utknąłem na dwóch problemach: #ifdefs odwołuje się do wielu tokenów, które NIE są właściwie zdefiniowane gdziekolwiek w kodzie Perla, które mogę znaleźć - i nie wiem, jak się dowiedzieć w Perlu, jakie były wartości define, i ostateczna wartość domyślna (zakładając, że mam rację, i te #ifdef s zawsze kończą się wartością domyślną) z #define PERL_USHORT_MAX ((unsigned short)~(unsigned)0) (Faktyczny limit jest uzyskiwany przez usunięcie 1-bitowego off, który daje wynik all-one number - szczegóły poniżej).

    Nie jestem również pewien, jak uzyskać dostęp do ilości bajtów w short z Perla dla dowolnej implementacji użytej do zbudowania pliku wykonywalnego perl.

    Tak więc, nawet jeśli odpowiedź na oba te pytania znajdzie się (czego nie jestem pewien), wynikowa logika byłaby z pewnością "brzydsza" i bardziej złożona niż prosta "empiryczna ewaluacja". Zaproponowałem jako pierwszą opcję.

Poniżej zapewni szczegóły gdzie różne kawałki logiki związanej z tym limitem żywo w kodzie Perl, a także moich próbach przybyć „Teoretycznie” prawidłowego dopasowania rozwiązanie C logiki.


OK, tutaj jest jakaś część dochodzenie sposób można to zakończyć się jak mam ti bieg albo będę zakończyć później:

  • Od regcomp.c: vFAIL2("Quantifier in {,} bigger than %d", REG_INFTY - 1);

    Tak, limit jest oczywiście brany z definicji REG_INFTY. Która jest zadeklarowana w:

  • rehcomp.h:

    /* XXX fix this description. 
        Impose a limit of REG_INFTY on various pattern matching operations 
        to limit stack growth and to avoid "infinite" recursions. 
    */ 
    /* The default size for REG_INFTY is I16_MAX, which is the same as 
        SHORT_MAX (see perl.h). Unfortunately I16 isn't necessarily 16 bits 
        (see handy.h). On the Cray C90, sizeof(short)==4 and hence I16_MAX is 
        ((1<<31)-1), while on the Cray T90, sizeof(short)==8 and I16_MAX is 
        ((1<<63)-1). To limit stack growth to reasonable sizes, supply a 
        smaller default. 
         --Andy Dougherty 11 June 1998 
    */ 
    #if SHORTSIZE > 2 
    # ifndef REG_INFTY 
    # define REG_INFTY ((1<<15)-1) 
    # endif 
    #endif 
    #ifndef REG_INFTY 
    # define REG_INFTY I16_MAX 
    #endif 
    

    Uwaga SHORTSIZE jest przeciążać poprzez Config - Odejdę szczegóły, które się jednak logika będą musiały zawierać $Config{shortsize} :)

  • Od handy.h (na pierwszy rzut oka nie wydaje się, że jest to część źródła Perla, więc wygląda na krok niepewny):

    #if defined(UINT8_MAX) && defined(INT16_MAX) && defined(INT32_MAX) 
    #define I16_MAX INT16_MAX 
    #else 
    #define I16_MAX PERL_SHORT_MAX 
    
  • nie mogłem znaleźć ANY miejsce, które zdefiniowane INT16_MAX wcale :(

    ktoś może pomóc proszę !!!

  • PERL_SHORT_MAX jest zdefiniowana w perl.h:

    #ifdef SHORT_MAX 
    # define PERL_SHORT_MAX ((short)SHORT_MAX) 
    #else 
    # ifdef MAXSHORT /* Often used in <values.h> */ 
    # define PERL_SHORT_MAX ((short)MAXSHORT) 
    # else 
    # ifdef SHRT_MAX 
    #  define PERL_SHORT_MAX ((short)SHRT_MAX) 
    # else 
    #  define PERL_SHORT_MAX  ((short) (PERL_USHORT_MAX >> 1)) 
    # endif 
    # endif 
    #endif 
    

    nie udało mi się znaleźć żadnego miejsca, które zdefiniowane SHORT_MAX, MAXSHORT lub SHRT_MAX tak daleko. Więc domyślna ((short) (PERL_USHORT_MAX >> 1)) zakłada się na razie :)

  • PERL_USHORT_MAX jest definiowana bardzo podobnie w perl.h i znowu nie mogłem znaleźć śladu definicji USHORT_MAX/MAXUSHORT/USHRT_MAX.

    Co wydaje się sugerować, że jest ustawione domyślnie na: #define PERL_USHORT_MAX ((unsigned short)~(unsigned)0). Jak wyodrębnić tę wartość ze strony Perla, nie mam pojęcia - jest to w zasadzie liczba uzyskana przez bitowe zanegowanie krótkiego 0, więc jeśli unsigned short ma 16 bajtów, to PERL_USHORT_MAX będzie 16, a PERL_SHORT_MAX będzie 15, np. 2^15-1, np. 32767.

  • Również z t/re/pat.t (badania): $::reg_infty = $Config {reg_infty} // 32767; regex (ilustrujących, w których zestawiane niż domyślna wartość jest przechowywana).

Tak więc, aby uzyskać stałą, robisz:

use Config; 
my $shortsize = $Config{shortsize} // 2; 
$c_reg_infty = (defined $Config {reg_infty}) ? $Config {reg_infty} 
              : ($shortsize > 2) ? 2**16-1 
              : get_PERL_SHORT_MAX(); 
# Where get_PERL_SHORT_MAX() depends on logic for PERL_SHORT_MAX in perl.h 
# which I'm not sure how to extract into Perl with any precision 
# due to a bunch of never-seen "#define"s and unknown size of "short". 
# You can probably do fairly well by simply returning 2**8-1 if shortsize==1 
# and 2^^16-1 otherwise. 
say "REAL reg_infinity based on C headers: $c_reg_infty"; 
+0

Open source jest jak nauka: wszyscy uzyskujemy takie same wyniki! : D – l0b0

+0

OK, w tym momencie myślę, że doszedłem do końca mojej wiedzy na temat wewnętrznych elementów Perla - ktoś z większą wskazówką, proszę o wskazanie mi siebie i OP, w jaki sposób ustalić prawidłowe wartości dla 'PERL_SHORT_MAX' i' INT16_MAX' definiuje z w samym Perlu, jeśli to możliwe. – DVK

+0

Najlepsze, co mogłem wymyślić, to "Devel-PPPort/parts/inc/limits", ale to wygląda na niewłaściwe podejście. – DVK