summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorJohn Peacock <jpeacock@rowman.com>2003-07-08 18:05:38 -0700
committerJarkko Hietaniemi <jhi@iki.fi>2003-07-09 06:58:39 +0000
commitf333445c29f1556015c4df0c417df8e1a742d36d (patch)
tree7e58fc16146315ff89d4c7c5d04390faa867f397 /toke.c
parent9a33f774ee40a20ac08cacf3360fea9af2b7ff5d (diff)
downloadperl-f333445c29f1556015c4df0c417df8e1a742d36d.tar.gz
Re: [REPATCH] was Re: [perl #16010] v-strings left of a => don't get quoted.
Message-ID: <3F0BCCD2.1020009@rowman.com> p4raw-id: //depot/perl@20084
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/toke.c b/toke.c
index bac0380c07..4c8fbe5be6 100644
--- a/toke.c
+++ b/toke.c
@@ -7958,3 +7958,90 @@ utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen)
}
#endif
+/*
+Returns a pointer to the next character after the parsed
+vstring, as well as updating the passed in sv.
+
+Function must be called like
+
+ sv = NEWSV(92,5);
+ s = scan_vstring(s,sv);
+
+The sv should already be large enough to store the vstring
+passed in, for performance reasons.
+
+*/
+
+char *
+Perl_scan_vstring(pTHX_ char *s, SV *sv)
+{
+ char *pos = s;
+ char *start = s;
+ if (*pos == 'v') pos++; /* get past 'v' */
+ while (isDIGIT(*pos) || *pos == '_')
+ pos++;
+ if ( *pos != '.') {
+ /* this may not be a v-string if followed by => */
+ start = pos;
+ if (isSPACE(*start))
+ start = skipspace(start);
+ if ( *start == '=' && start[1] == '>' )
+ {
+ /* return string not v-string */
+ sv_setpvn(sv,(char *)s,pos-s);
+ return pos;
+ }
+ }
+
+ if (!isALPHA(*pos)) {
+ UV rev;
+ U8 tmpbuf[UTF8_MAXLEN+1];
+ U8 *tmpend;
+
+ if (*s == 'v') s++; /* get past 'v' */
+
+ sv_setpvn(sv, "", 0);
+
+ for (;;) {
+ 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_ packWARN(WARN_OVERFLOW),
+ "Integer overflow in decimal number");
+ }
+ }
+#ifdef EBCDIC
+ if (rev > 0x7FFFFFFF)
+ Perl_croak(aTHX_ "In EBCDIC the v-string components cannot exceed 2147483647");
+#endif
+ /* Append native character for the rev point */
+ tmpend = uvchr_to_utf8(tmpbuf, rev);
+ sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
+ if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
+ SvUTF8_on(sv);
+ if (*pos == '.' && isDIGIT(pos[1]))
+ s = ++pos;
+ else {
+ s = pos;
+ break;
+ }
+ while (isDIGIT(*pos) || *pos == '_')
+ pos++;
+ }
+ SvPOK_on(sv);
+ sv_magic(sv,NULL,PERL_MAGIC_vstring,(const char*)start, pos-start);
+ SvRMAGICAL_on(sv);
+ }
+ return s;
+}
+