Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Summary: there are 3 ways I can think of to find the limit: empirical, "matching Perl tests" and "theoretical".</p> <ul> <li><p>Empirical: </p> <pre><code>eval {$_ **= $_ , / {$_} / for 2 .. 129}; # To be truly portable, the above should ideally loop forever till $@ is true. $@ =~ /bigger than (-?\d+) /; print "LIMIT: $1\n"' </code></pre> <p>This seems obvious enough that it doesn't require explanation.</p></li> <li><p>Matches Perl tests:</p> <p>Perl has a series of tests for regex, some of which (in <code>pat.t</code>) deal with testing this max value. So, you can approximate that the max value computed in those tests is "good enough" and follow the test's logic:</p> <pre><code>use Config; $reg_infty = $Config {reg_infty} // 2 ** 15 - 1; # 32767 print "Test-based reg_infinity limit: $reg_infty\n"; </code></pre> <p>The explanation of where in the tests this is based off of is in below details.</p></li> <li><p>Theoretical: This is attempting to replicate the EXACT logic used by C code to generate this value.</p> <p>This is harder that it sounds, because it's affected by 2 things: Perl build configuration and a bunch of C <code>#define</code> statements with branching logic. I was able to delve fairly deeply into that logic, but was stalled on two problems: the <code>#ifdefs</code> reference a bunch of tokens that are NOT actually defined anywhere in Perl code that I can find - and I don't know how to find out from within Perl what those <code>define</code>s values were, and the ultimate default value (assuming I'm right and those <code>#ifdef</code>s always end up with the default) of <code>#define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)</code> (The actual limit is gotten by removing 1 bit off that resulting all-ones number - details below). </p> <p>I'm also not sure how to access the amount of bytes in <code>short</code> from Perl for whichever implementation was used to build <code>perl</code> executable. </p> <p>So, even if the answer to both those questions can be found (which I'm not sure of), the resulting logic would most certainly be "uglier" and more complex than the straightforward "empirical eval-based" one I offered as the first option.</p></li> </ul> <p>Below I will provide the details of where various bits and pieces of logic related to to this limit live in Perl code, as well as my attempts to arrive at "Theoretically correct" solution matching C logic.</p> <hr> <p>OK, here is some investigation part way, you can complete it yourself as I have ti run or I will complete later:</p> <ul> <li><p>From <a href="http://perl5.git.perl.org/perl.git?a=search&amp;h=HEAD&amp;st=grep&amp;s=Quantifier+in" rel="nofollow"><code>regcomp.c</code></a>: <code>vFAIL2("Quantifier in {,} bigger than %d", REG_INFTY - 1);</code></p> <p>So, the limit is obviously taken from <code>REG_INFTY</code> define. Which is declared in:</p></li> <li><p><a href="http://perl5.git.perl.org/perl.git/blob?f=regcomp.h" rel="nofollow"><code>rehcomp.h</code></a>:</p> <pre><code> /* 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&lt;&lt;31)-1), while on the Cray T90, sizeof(short)==8 and I16_MAX is ((1&lt;&lt;63)-1). To limit stack growth to reasonable sizes, supply a smaller default. --Andy Dougherty 11 June 1998 */ #if SHORTSIZE &gt; 2 # ifndef REG_INFTY # define REG_INFTY ((1&lt;&lt;15)-1) # endif #endif #ifndef REG_INFTY # define REG_INFTY I16_MAX #endif </code></pre> <p>Please note that SHORTSIZE is overridable via <code>Config</code> - I will leave details of that out but the logic will need to include <code>$Config{shortsize}</code> :)</p></li> <li><p>From handy.h (this doesn't seem to be part of Perl source at first glance so it looks like an iffy step): </p> <pre><code> #if defined(UINT8_MAX) &amp;&amp; defined(INT16_MAX) &amp;&amp; defined(INT32_MAX) #define I16_MAX INT16_MAX #else #define I16_MAX PERL_SHORT_MAX </code></pre></li> <li><p>I could not find <strong>ANY</strong> place which defined <code>INT16_MAX</code> at all :(</p> <p>Someone help please!!!</p></li> <li><p>PERL_SHORT_MAX is defined in perl.h:</p> <pre><code> #ifdef SHORT_MAX # define PERL_SHORT_MAX ((short)SHORT_MAX) #else # ifdef MAXSHORT /* Often used in &lt;values.h&gt; */ # 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 &gt;&gt; 1)) # endif # endif #endif </code></pre> <p>I wasn't able to find any place which defined SHORT_MAX, MAXSHORT or SHRT_MAX so far. So the default of <code>((short) (PERL_USHORT_MAX &gt;&gt; 1))</code> it is assumed to be for now :)</p></li> <li><p>PERL_USHORT_MAX is defined very similarly in <code>perl.h</code>, and again I couldn't find a trace of definition of <code>USHORT_MAX</code>/<code>MAXUSHORT</code>/<code>USHRT_MAX</code>. </p> <p>Which seems to imply that it's set by default to: <code>#define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)</code>. How to extract that value from Perl side, I have no clue - it's basically a number you get by bitwise negating a short 0, so if unsigned short is 16 bytes, then <code>PERL_USHORT_MAX</code> will be 16 ones, and <code>PERL_SHORT_MAX</code> will be 15 ones, e.g. 2^15-1, e.g. 32767. </p></li> <li><p>Also, from <a href="http://perl5.git.perl.org/perl.git?a=search&amp;h=HEAD&amp;st=grep&amp;s=REG_INFTY" rel="nofollow"><code>t/re/pat.t</code></a> (regex tests): <code>$::reg_infty = $Config {reg_infty} // 32767;</code> (to illustrate where the non-default compiled in value is stored).</p></li> </ul> <p>So, to get your constant, you do:</p> <pre><code>use Config; my $shortsize = $Config{shortsize} // 2; $c_reg_infty = (defined $Config {reg_infty}) ? $Config {reg_infty} : ($shortsize &gt; 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"; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload