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<print 97.98.99> used to output C<97.9899> in earlier
+versions, but now prints C<abc>.
+
+See L<Support for strings represented as a vector of ordinals> below.
+
=item Possibly changed pseudo-random number generator
In 5.005_0x and earlier, perl's rand() function used the C library
=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<v1.2.3.4> 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<v> may be omitted if there are more than two ordinals, so C<1.2.3> is
+parsed the same as C<v1.2.3>.
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
require v5.6.0; # croak if $^V lt v5.6.0
use v5.6.0; # same, but croaks at compile-time
+Alternatively, the C<v> may be omitted if there is more than one dot:
+
+ require 5.6.0;
+ use 5.6.0;
+
Also, C<sprintf> and C<printf> 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<perlop/"Strings of Character"> for additional information.
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</use>, 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
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<use locale> is in effect, the character used for the decimal
point in formatted real numbers is affected by the LC_NUMERIC locale.
except that Module I<must> 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
parse the rest of the file. Compare with L</require>, 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
C<use>ing library modules that have changed in incompatible ways from
for representing Unicode strings, and for comparing version "numbers"
using the string comparison operators, C<cmp>, C<gt>, C<lt> etc.
+If there are more than two dots in the literal, the leading C<v> may be
+omitted.
+
Such literals are accepted by both C<require> and C<use> for doing a version
check. The C<$^V> special variable also contains the running Perl
interpreter's version in this form. See L<perlvar/$^V>.
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";
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";
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";
{
unshift @INC, "../lib";
}
-print "1..18\n";
+print "1..22\n";
my $test = 1;
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;
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';
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';
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 */
}
char *start = s;
start++;
start++;
- while (isDIGIT(*start))
+ while (isDIGIT(*start) || *start == '_')
start++;
if (*start == '.' && isDIGIT(start[1])) {
s = scan_num(s);
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 */
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;
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);
s = pos;
break;
}
- while (isDIGIT(*pos))
+ while (isDIGIT(*pos) || *pos == '_')
pos++;
}