2011-01-04 2 views
6

От man perlre: "?"perlre предел длины

Символ "*" квантификатором эквивалентно "{0}", на "+" квантификатором на "{1}", и квантификатор к "{0,1}". n и m ограничены интегральными значениями, меньшими заданного предела, определяемого при построении perl. Обычно это 32766 на наиболее распространенных платформах. Фактический предел может быть видно в сообщении об ошибке, генерируемого кода, как это:

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

Ay, что некрасиво - есть не какая-то константа я могу получить взамен?

Редактировать: Как указал Даксим (и perlretut намеков), возможно, 32767 является магическим жестко запрограммированным номером. в коде Perl Немного searching проходит долгий путь, но я не уверен, как получить к следующему шагу и на самом деле выяснить, где reg_infty или REG_INFTY по умолчанию фактически установлено:

~/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 конечно, правильно: это define d во время компиляции, и, вероятно, можно переопределить только REG_INFTY.

+5

Также см http://perl.plover.com/yak/regex/samples/slide050.html – daxim

+0

@daxim: я думаю, у вас есть полный ответ, а не только комментарий. «Даже если бы вы знали предел, это не было бы полезным номером, потому что двигатель регулярного выражения, скорее всего, умрет, прежде чем он достигнет теоретического предела». –

ответ

8

Реферат: Есть три способа найти предел: эмпирический, «сопоставление тестов Perl» и «теоретический».

  • Эмпирические:

    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"' 
    

    Это кажется достаточно очевидным, что она не требует объяснений.

  • Матчи Perl тесты:

    Perl имеет ряд тестов для регулярных выражений, некоторые из которых (в pat.t) сделки с тестирования этого максимального значения. Таким образом, вы можете приблизить, что значение макс вычисляется в этих тестах «достаточно хорошо» и следовать логике Теста в:

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

    Объяснение того, где в тестах это базируется прочь находится в детали ниже.

  • Теоретический: Это попытка реплицировать логику EXACT, используемую кодом C, для генерации этого значения.

    Это сложнее, чем кажется, потому что на него влияют две вещи: конфигурация сборки Perl и куча C #define операторов с логикой ветвления. Я смог довольно глубоко вникать в эту логику, но был остановлен на двух проблемах: ссылка #ifdefs ссылается на кучу токенов, которые на самом деле не определены в любом месте кода Perl, который я могу найти, - и я не знаю, как узнать из в пределах Perl значения этих define s и конечное значение по умолчанию (при условии, что я прав, и те, что #ifdef s всегда заканчиваются по умолчанию) #define PERL_USHORT_MAX ((unsigned short)~(unsigned)0) (Фактический предел получен, удалив 1 бит из полученного итогового числа - подробности ниже).

    Я также не уверен, как получить доступ к количеству байтов в short от Perl для той, которая была реализована при построении perl исполняемого файла.

    Итак, даже если ответ на оба этих вопроса можно найти (что я не уверен), результирующая логика, безусловно, будет «уродливой» и более сложной, чем простая «эмпирическая оценка, основанная на оценках» Я предложил в качестве первого варианта.

Ниже я приведу детали, где различные биты и куски логики, связанной с этого предела, живут в коде Perl, а также мои попытки прийти «Теоретически правильное» решение согласования C логики.


ОК, вот некоторые следствия часть пути, вы можете заполнить его самостоятельно, как я ти бежать или я закончу позже:

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

    Таким образом, предел, очевидно, берется из REG_INFTY define. Который объявлен в:

  • 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 
    

    Пожалуйста, обратите внимание, что SHORTSIZE является переопределение через Config - Я оставлю подробности, что из но логика нужно будет включать в себя $Config{shortsize} :)

  • Из handy.h (это, кажется, не является частью источника Perl с первого взгляда, поэтому он выглядит как шаг iffy):

    #if defined(UINT8_MAX) && defined(INT16_MAX) && defined(INT32_MAX) 
    #define I16_MAX INT16_MAX 
    #else 
    #define I16_MAX PERL_SHORT_MAX 
    
  • Я не мог найти ANY место, которое определено INT16_MAX вообще :(

    Кто-то пожалуйста, помогите !!!

  • PERL_SHORT_MAX определяется в 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 
    

    Я не смог найти место, которое определено SHORT_MAX, MAXSHORT или SHRT_MAX до сих пор. Поэтому по умолчанию ((short) (PERL_USHORT_MAX >> 1)) предполагается, что на данный момент :)

  • PERL_USHORT_MAX определяется очень сходно в perl.h, и снова я не мог найти след определения USHORT_MAX/MAXUSHORT/USHRT_MAX.

    Это, по-видимому, означает, что оно установлено по умолчанию: #define PERL_USHORT_MAX ((unsigned short)~(unsigned)0). Как извлечь это значение со стороны Perl, у меня нет подсказки - это в основном номер, который вы получаете по побитовому отрицанию короткого 0, так что если unsigned short равно 16 байтам, то PERL_USHORT_MAX будет 16, а PERL_SHORT_MAX будет равен 15, например. 2^15-1, например. 32767.

  • Также из t/re/pat.t (регулярные выражения): $::reg_infty = $Config {reg_infty} // 32767; (для иллюстрации, где хранится не скомпилированное по умолчанию значение).

Таким образом, чтобы получить постоянную, вы делаете:

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

Открытый исходник - это наука: все мы получаем одинаковые результаты! : D – l0b0

+0

ОК, на данный момент я думаю, что дошел до конца своих знаний о внутренних функциях Perl - кто-то с большим количеством подсказок, подскажите как себя, так и OP в том, как узнать правильные значения для 'PERL_SHORT_MAX' и' INT16_MAX', определяет из в самом Perl, если это возможно. – DVK

+0

Лучшее, что я мог придумать, было «Devel-PPPort/parts/inc/limits», но это похоже на неправильный подход – DVK