summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2016-07-26 01:46:23 -0700
committerFather Chrysostomos <sprout@cpan.org>2016-07-26 01:52:25 -0700
commitcb6501357462af503ffcfa2608d54a8336e1f244 (patch)
tree3c35f9d891161febd0914eeb6dfec955cae3e6c5
parent6745174b5616843ee57f0b733bd056bfab42f30f (diff)
downloadperl-cb6501357462af503ffcfa2608d54a8336e1f244.tar.gz
[perl #128701] Fix err msg for Unicode delimiters
The output of perl -CS -e 'use utf8; q«' is now correctly: Can't find string terminator "«" anywhere before EOF at -e line 1. Previously, the first byte of the delimiter (as encoded in UTF-8) would be used instead: Can't find string terminator "Â" anywhere before EOF at -e line 1.
-rw-r--r--t/lib/croak/toke14
-rw-r--r--toke.c26
2 files changed, 33 insertions, 7 deletions
diff --git a/t/lib/croak/toke b/t/lib/croak/toke
index 1c6e4a221e..cda6ffd53a 100644
--- a/t/lib/croak/toke
+++ b/t/lib/croak/toke
@@ -85,6 +85,20 @@ Can't find string terminator "/" anywhere before EOF at - line 1.
EXPECT
Can't find string terminator "'" anywhere before EOF at - line 1.
########
+# NAME Unterminated q// with non-ASCII delimiter, under utf8
+BEGIN { binmode STDERR, ":utf8" }
+use utf8;
+q«
+EXPECT
+Can't find string terminator "«" anywhere before EOF at - line 3.
+########
+# NAME Unterminated q// with non-Latin-1 delimiter
+BEGIN { binmode STDERR, ":utf8" }
+use utf8;
+q 옷
+EXPECT
+Can't find string terminator "옷" anywhere before EOF at - line 3.
+########
# NAME /\N{/
/\N{/
EXPECT
diff --git a/toke.c b/toke.c
index d92723aa59..13d8c3e151 100644
--- a/toke.c
+++ b/toke.c
@@ -555,26 +555,38 @@ S_no_op(pTHX_ const char *const what, char *s)
STATIC void
S_missingterm(pTHX_ char *s)
{
- char tmpbuf[3];
+ char tmpbuf[UTF8_MAXBYTES];
char q;
+ bool uni = FALSE;
+ SV *sv;
if (s) {
char * const nl = strrchr(s,'\n');
if (nl)
*nl = '\0';
}
- else if ((U8) PL_multi_close < 32) {
+ else if (PL_multi_close < 32) {
*tmpbuf = '^';
tmpbuf[1] = (char)toCTRL(PL_multi_close);
tmpbuf[2] = '\0';
s = tmpbuf;
}
else {
- *tmpbuf = (char)PL_multi_close;
- tmpbuf[1] = '\0';
+ if (LIKELY(PL_multi_close < 256)) {
+ *tmpbuf = (char)PL_multi_close;
+ tmpbuf[1] = '\0';
+ }
+ else {
+ uni = TRUE;
+ *uvchr_to_utf8((U8 *)tmpbuf, PL_multi_close) = 0;
+ }
s = tmpbuf;
}
q = strchr(s,'"') ? '\'' : '"';
- Perl_croak(aTHX_ "Can't find string terminator %c%s%c anywhere before EOF",q,s,q);
+ sv = sv_2mortal(newSVpv(s,0));
+ if (uni)
+ SvUTF8_on(sv);
+ Perl_croak(aTHX_ "Can't find string terminator %c%"SVf
+ "%c anywhere before EOF",q,SVfARG(sv),q);
}
#include "feature.h"
@@ -9947,14 +9959,14 @@ S_scan_str(pTHX_ char *start, int keep_bracketed_quoted, int keep_delims, int re
/* mark where we are */
PL_multi_start = CopLINE(PL_curcop);
- PL_multi_open = term;
+ PL_multi_open = termcode;
herelines = PL_parser->herelines;
/* find corresponding closing delimiter */
if (term && (tmps = strchr("([{< )]}> )]}>",term)))
termcode = termstr[0] = term = tmps[5];
- PL_multi_close = term;
+ PL_multi_close = termcode;
if (PL_multi_open == PL_multi_close) {
keep_bracketed_quoted = FALSE;