per Larry's idea, parse 1.2.3 as v1.2.3; C<require 5.6.0> and
Gurusamy Sarathy [Wed, 23 Feb 2000 09:10:43 +0000 (09:10 +0000)]
C<use 5.6.0> work as well; underscores are now permitted in v-strings

p4raw-id: //depot/perl@5220

pod/perldelta.pod
pod/perlfunc.pod
pod/perlop.pod
t/comp/require.t
t/op/ver.t
toke.c

index d908567..4fd3ce4 100644 (file)
@@ -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<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
@@ -461,10 +473,12 @@ variables.  See L<perlfunc/our>.
 
 =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
@@ -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<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.
 
index f4cee09..d4215b6 100644 (file)
@@ -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</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
@@ -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<use locale> 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<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
@@ -5264,8 +5265,9 @@ message is printed and Perl exits immediately without attempting to
 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
index 7cb3450..bc6f2ce 100644 (file)
@@ -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<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>.
index cd97c55..efce899 100755 (executable)
@@ -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";
 
 {
index 206b1d0..b08849f 100755 (executable)
@@ -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 (file)
--- 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++;
                }