From: Gurusamy Sarathy Date: Wed, 23 Feb 2000 09:10:43 +0000 (+0000) Subject: per Larry's idea, parse 1.2.3 as v1.2.3; C and X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=dd629d5bb3bd7014585b7aad3c6715a5011673bc;p=p5sagit%2Fp5-mst-13.2.git per Larry's idea, parse 1.2.3 as v1.2.3; C and C work as well; underscores are now permitted in v-strings p4raw-id: //depot/perl@5220 --- diff --git a/pod/perldelta.pod b/pod/perldelta.pod index d908567..4fd3ce4 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -84,6 +84,18 @@ notation, 5.005_03 is the same as v5.5.30, and the first maintenance version following v5.6.0 will be v5.6.1, which amounts to a floating point value of 5.006_001). +=item Literals of the form C<1.2.3> parse differently + +Previously, numeric literals with more than one dot in them were +interpreted as a floating point number concatenated with one or more +numbers. Such "numbers" are now parsed as strings composed of the +specified ordinals. + +For example, C used to output C<97.9899> in earlier +versions, but now prints C. + +See L below. + =item Possibly changed pseudo-random number generator In 5.005_0x and earlier, perl's rand() function used the C library @@ -461,10 +473,12 @@ variables. See L. =head2 Support for strings represented as a vector of ordinals -Literals of the form v1.2.3.4 are now parsed as a string composed of +Literals of the form C are now parsed as a string composed of of characters with the specified ordinals. This is an alternative, more readable way to construct (possibly unicode) strings instead of -interpolating characters, as in C<"\x{1}\x{2}\x{3}\x{4}">. +interpolating characters, as in C<"\x{1}\x{2}\x{3}\x{4}">. The leading +C may be omitted if there are more than two ordinals, so C<1.2.3> is +parsed the same as C. Strings written in this form are also useful to represent version "numbers". It is easy to compare such version "numbers" (which are really just plain @@ -487,12 +501,17 @@ They will be interpreted as a version rather than as a module name: require v5.6.0; # croak if $^V lt v5.6.0 use v5.6.0; # same, but croaks at compile-time +Alternatively, the C may be omitted if there is more than one dot: + + require 5.6.0; + use 5.6.0; + Also, C and C support the Perl-specific format flag C<%v> to print ordinals of characters in arbitrary strings: printf "v%vd", $^V; # prints current version, such as "v5.5.650" printf "%*vX", ":", $addr; # formats IPv6 address - printf "%*vb", "", $bits; # displays bitstring as contiguous 0's and 1's + printf "%*vb", " ", $bits; # displays bitstring See L for additional information. diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index f4cee09..d4215b6 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -3551,15 +3551,16 @@ rename(2) manpage or equivalent system documentation for details. Demands some semantics specified by EXPR, or by C<$_> if EXPR is not supplied. -If a VERSION is specified as a literal of the form v5.6.0, +If a VERSION is specified as a literal of the form v5.6.1, demands that the current version of Perl (C<$^V> or $PERL_VERSION) be at least as recent as that version, at run time. (For compatibility with older versions of Perl, a numeric argument will also be interpreted as VERSION.) Compare with L, which can do a similar check at compile time. - require v5.6.0; # run time version check - require 5.005_03; # same, number still supported for compatibility + require v5.6.1; # run time version check + require 5.6.1; # ditto + require 5.005_03; # float version allowed for compatibility Otherwise, demands that a library file be included if it hasn't already been included. The file is included via the do-FILE mechanism, which is @@ -4389,7 +4390,7 @@ in arbitrary strings: printf "version is v%vd\n", $^V; # Perl's version printf "address is %*vX\n", ":", $addr; # IPv6 address - printf "bits are %*vb\n", "", $bits; # random bitstring + printf "bits are %*vb\n", " ", $bits; # random bitstring If C is in effect, the character used for the decimal point in formatted real numbers is affected by the LC_NUMERIC locale. @@ -5255,7 +5256,7 @@ package. It is exactly equivalent to except that Module I be a bareword. -VERSION, which can be specified as a literal of the form v5.6.0, demands +VERSION, which can be specified as a literal of the form v5.6.1, demands that the current version of Perl (C<$^V> or $PERL_VERSION) be at least as recent as that version. (For compatibility with older versions of Perl, a numeric literal will also be interpreted as VERSION.) If the version @@ -5264,8 +5265,9 @@ message is printed and Perl exits immediately without attempting to parse the rest of the file. Compare with L, which can do a similar check at run time. - use v5.6.0; # compile time version check - use 5.005_03; # same, number still supported for compatibility + use v5.6.1; # compile time version check + use 5.6.1; # ditto + use 5.005_03; # float version allowed for compatibility This is often useful if you need to check the current Perl version before Cing library modules that have changed in incompatible ways from diff --git a/pod/perlop.pod b/pod/perlop.pod index 7cb3450..bc6f2ce 100644 --- a/pod/perlop.pod +++ b/pod/perlop.pod @@ -1811,6 +1811,9 @@ readable interpolation form C<"\x{1}\x{14}\x{12c}\x{fa0}">. This is useful for representing Unicode strings, and for comparing version "numbers" using the string comparison operators, C, C, C etc. +If there are more than two dots in the literal, the leading C may be +omitted. + Such literals are accepted by both C and C for doing a version check. The C<$^V> special variable also contains the running Perl interpreter's version in this form. See L. diff --git a/t/comp/require.t b/t/comp/require.t index cd97c55..efce899 100755 --- a/t/comp/require.t +++ b/t/comp/require.t @@ -47,7 +47,7 @@ eval { require v5.5.630; }; print "# $@\nnot " if $@; print "ok ",$i++,"\n"; -eval { require v10.0.2; }; +eval { require 10.0.2; }; print "# $@\nnot " unless $@ =~ /^Perl v10\.0\.2 required/; print "ok ",$i++,"\n"; @@ -55,7 +55,7 @@ eval q{ use v5.5.630; }; print "# $@\nnot " if $@; print "ok ",$i++,"\n"; -eval q{ use v10.0.2; }; +eval q{ use 10.0.2; }; print "# $@\nnot " unless $@ =~ /^Perl v10\.0\.2 required/; print "ok ",$i++,"\n"; @@ -75,7 +75,7 @@ eval { require $ver; }; print "# $@\nnot " unless $@ =~ /^Perl v10\.0\.20 required/; print "ok ",$i++,"\n"; -print "not " unless v5.5.1 gt v5.5; +print "not " unless 5.5.1 gt v5.5; print "ok ",$i++,"\n"; { diff --git a/t/op/ver.t b/t/op/ver.t index 206b1d0..b08849f 100755 --- a/t/op/ver.t +++ b/t/op/ver.t @@ -5,7 +5,7 @@ BEGIN { unshift @INC, "../lib"; } -print "1..18\n"; +print "1..22\n"; my $test = 1; @@ -35,6 +35,24 @@ print "ok $test\n"; ++$test; print "not " unless v1.20.300.4000 eq "\x{1}\x{14}\x{12c}\x{fa0}"; print "ok $test\n"; ++$test; +# +# now do the same without the "v" +use 5.5.640; +require 5.5.640; +print "ok $test\n"; ++$test; + +# hash keys too +$h{111.107.32} = "ok"; +print "$h{ok } $test\n"; ++$test; + +$x = 77.78.79; +print "not " unless $x eq "MNO"; +print "ok $test\n"; ++$test; + +print "not " unless 1.20.300.4000 eq "\x{1}\x{14}\x{12c}\x{fa0}"; +print "ok $test\n"; ++$test; + +# test sprintf("%vd"...) etc print "not " unless sprintf("%vd", "Perl") eq '80.101.114.108'; print "ok $test\n"; ++$test; @@ -44,7 +62,7 @@ print "ok $test\n"; ++$test; print "not " unless sprintf("%vx", "Perl") eq '50.65.72.6c'; print "ok $test\n"; ++$test; -print "not " unless sprintf("%vX", v1.22.333.4444) eq '1.16.14D.115C'; +print "not " unless sprintf("%vX", 1.22.333.4444) eq '1.16.14D.115C'; print "ok $test\n"; ++$test; print "not " unless sprintf("%*v#o", ":", "Perl") eq '0120:0145:0162:0154'; @@ -60,7 +78,7 @@ print "ok $test\n"; ++$test; print "ok $test\n"; ++$test; print "not " unless - sprintf("%vd", v1.22.333.4444) eq '1.22.197.141.225.133.156'; + sprintf("%vd", 1.22.333.4444) eq '1.22.197.141.225.133.156'; print "ok $test\n"; ++$test; print "not " unless sprintf("%vx", "Perl") eq '50.65.72.6c'; diff --git a/toke.c b/toke.c index a7ceba3..5347ecd 100644 --- a/toke.c +++ b/toke.c @@ -821,24 +821,22 @@ STATIC char * S_force_version(pTHX_ char *s) { OP *version = Nullop; - bool is_vstr = FALSE; char *d; s = skipspace(s); d = s; - if (*d == 'v') { - is_vstr = TRUE; + if (*d == 'v') d++; - } if (isDIGIT(*d)) { for (; isDIGIT(*d) || *d == '_' || *d == '.'; d++); if (*d == ';' || isSPACE(*d) || *d == '}' || !*d) { + SV *ver; s = scan_num(s); /* real VERSION number -- GBARR */ version = yylval.opval; - if (is_vstr) { - SV *ver = cSVOPx(version)->op_sv; + ver = cSVOPx(version)->op_sv; + if (SvPOK(ver) && !SvNIOK(ver)) { SvUPGRADE(ver, SVt_PVIV); SvIOKp_on(ver); /* hint that it is a version */ } @@ -3499,7 +3497,7 @@ Perl_yylex(pTHX) char *start = s; start++; start++; - while (isDIGIT(*start)) + while (isDIGIT(*start) || *start == '_') start++; if (*start == '.' && isDIGIT(start[1])) { s = scan_num(s); @@ -6886,6 +6884,11 @@ Perl_scan_num(pTHX_ char *start) if (*s != '_') *d++ = *s; } + if (*s == '.' && isDIGIT(s[1])) { + /* oops, it's really a v-string, but without the "v" */ + s = start - 1; + goto vstring; + } } /* read exponent part, if present */ @@ -6939,10 +6942,11 @@ Perl_scan_num(pTHX_ char *start) break; /* if it starts with a v, it could be a version number */ case 'v': +vstring: { char *pos = s; pos++; - while (isDIGIT(*pos)) + while (isDIGIT(*pos) || *pos == '_') pos++; if (!isALPHA(*pos)) { UV rev; @@ -6957,7 +6961,23 @@ Perl_scan_num(pTHX_ char *start) for (;;) { if (*s == '0' && isDIGIT(s[1])) yyerror("Octal number in vector unsupported"); - rev = atoi(s); + rev = 0; + { + /* this is atoi() that tolerates underscores */ + char *end = pos; + UV mult = 1; + while (--end >= s) { + UV orev; + if (*end == '_') + continue; + orev = rev; + rev += (*end - '0') * mult; + mult *= 10; + if (orev > rev && ckWARN_d(WARN_OVERFLOW)) + Perl_warner(aTHX_ WARN_OVERFLOW, + "Integer overflow in decimal number"); + } + } tmpend = uv_to_utf8(tmpbuf, rev); utf8 = utf8 || rev > 127; sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf); @@ -6967,7 +6987,7 @@ Perl_scan_num(pTHX_ char *start) s = pos; break; } - while (isDIGIT(*pos)) + while (isDIGIT(*pos) || *pos == '_') pos++; }