来自man perlre:
"*"量词相当于"{0,}","+"量词相当于"{1,}"和"?" 量词为"{0,1}".n和m限于小于建立perl时定义的预设限制的整数值.在最常见的平台上,这通常是32766.实际限制可以在代码生成的错误消息中看到,例如:
Run Code Online (Sandbox Code Playgroud)$_ **= $_ , / {$_} / for 2 .. 42;
哎这很难看 - 难道不是我可以得到一些常数吗?
编辑:正如daxim指出的那样(并且perlretut提示)可能是32767是一个神奇的硬编码.在Perl代码中进行一些搜索有很长的路要走,但我不确定如何进入下一步并实际找出实际设置的默认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.
Run Code Online (Sandbox Code Playgroud)
编辑2:DVK当然是正确的:它是define在编译时,并且可能只能被覆盖REG_INFTY.
总结:我有三种方法可以想到找到极限:经验,"匹配Perl测试"和"理论".
经验:
eval {$_ **= $_ , / {$_} / for 2 .. 129};
# To be truly portable, the above should ideally loop forever till $@ is true.
$@ =~ /bigger than (-?\d+) /;
print "LIMIT: $1\n"'
Run Code Online (Sandbox Code Playgroud)
这似乎很明显,不需要解释.
匹配Perl测试:
Perl对正则表达式进行了一系列测试,其中一些(in pat.t)处理测试这个最大值.因此,您可以估算出在这些测试中计算的最大值"足够好"并遵循测试的逻辑:
use Config;
$reg_infty = $Config {reg_infty} // 2 ** 15 - 1; # 32767
print "Test-based reg_infinity limit: $reg_infty\n";
Run Code Online (Sandbox Code Playgroud)
在此基础上的测试中的解释如下.
理论:这是试图复制C代码使用的EXACT逻辑来生成此值.
这听起来更难,因为它受到两件事的影响:Perl构建配置和一堆#define带有分支逻辑的C 语句.我能够深入研究这个逻辑,但是在两个问题上停滞不前:#ifdefs引用了一堆令牌,这些令牌实际上并没有在我能找到的Perl代码中的任何地方定义 - 而且我不知道如何从内部找到Perl这些define值是什么,以及最终的默认值(假设我是正确的,并且那些#ifdef总是以默认值结束)#define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)(实际限制是通过删除1比特得到的全部数字得到的 - 详情如下) .
我也不确定如何使用shortPerl 来访问用于构建perl可执行文件的任何实现的字节数.
因此,即使可以找到这两个问题的答案(我也不确定),结果逻辑肯定会比我提供的直接的"基于经验评估"的逻辑"更丑"和更复杂.第一种选择.
下面我将提供Perl代码中与此限制相关的各种逻辑部分的详细信息,以及我尝试获得匹配C逻辑的"理论正确"解决方案.
好的,这是一些调查的一部分,你可以自己完成它,因为我已经运行或我将在稍后完成:
来自regcomp.c:vFAIL2("Quantifier in {,} bigger than %d", REG_INFTY - 1);
因此,限制显然来自于REG_INFTY定义.其中声明:
/* 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
Run Code Online (Sandbox Code Playgroud)
请注意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
Run Code Online (Sandbox Code Playgroud)我找不到任何定义的地方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
Run Code Online (Sandbox Code Playgroud)
到目前为止,我找不到任何定义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得到的数字,所以如果无符号短是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";
Run Code Online (Sandbox Code Playgroud)