#define yylval PL_yylval
static char ident_too_long[] = "Identifier too long";
+static char c_without_g[] = "Use of /c modifier is meaningless without /g";
+static char c_in_subst[] = "Use of /c modifier is meaningless in s///";
static void restore_rsfp(pTHX_ void *f);
#ifndef PERL_NO_UTF16_FILTER
#ifdef USE_UTF8_SCRIPTS
# define UTF (!IN_BYTES)
#else
-# ifdef EBCDIC /* For now 'use utf8' does not affect tokenizer on EBCDIC */
-# define UTF (PL_linestr && DO_UTF8(PL_linestr))
-# else
-# define UTF ((PL_linestr && DO_UTF8(PL_linestr)) || (PL_hints & HINT_UTF8))
-# endif
+# define UTF ((PL_linestr && DO_UTF8(PL_linestr)) || (PL_hints & HINT_UTF8))
#endif
/* In variables named $^X, these are the legal values for X.
/*
* S_ao
*
- * This subroutine detects &&= and ||= and turns an ANDAND or OROR
- * into an OP_ANDASSIGN or OP_ORASSIGN
+ * This subroutine detects &&=, ||=, and //= and turns an ANDAND, OROR or DORDOR
+ * into an OP_ANDASSIGN, OP_ORASSIGN, or OP_DORASSIGN
*/
STATIC int
yylval.ival = OP_ANDASSIGN;
else if (toketype == OROR)
yylval.ival = OP_ORASSIGN;
+ else if (toketype == DORDOR)
+ yylval.ival = OP_DORASSIGN;
toketype = ASSIGNOP;
}
return toketype;
s = tmpbuf;
}
else {
- *tmpbuf = PL_multi_close;
+ *tmpbuf = (char)PL_multi_close;
tmpbuf[1] = '\0';
s = tmpbuf;
}
if (SvREADONLY(PL_linestr))
PL_linestr = sv_2mortal(newSVsv(PL_linestr));
s = SvPV(PL_linestr, len);
- if (len && s[len-1] != ';') {
+ if (!len || s[len-1] != ';') {
if (!(SvFLAGS(PL_linestr) & SVs_TEMP))
PL_linestr = sv_2mortal(newSVsv(PL_linestr));
sv_catpvn(PL_linestr, "\n;", 2);
PL_expect = x;
PL_bufptr = s;
PL_last_lop = PL_oldbufptr;
- PL_last_lop_op = f;
+ PL_last_lop_op = (OPCODE)f;
if (PL_nexttoke)
return LSTOP;
if (*s == '(')
*PL_lex_casestack = '\0';
PL_lex_starts = 0;
PL_lex_state = LEX_INTERPCONCAT;
- CopLINE_set(PL_curcop, PL_multi_start);
+ CopLINE_set(PL_curcop, (line_t)PL_multi_start);
PL_lex_inwhat = PL_sublex_info.sub_inwhat;
if (PL_lex_inwhat == OP_MATCH || PL_lex_inwhat == OP_QR || PL_lex_inwhat == OP_SUBST)
It stops processing as soon as it finds an embedded $ or @ variable
and leaves it to the caller to work out what's going on.
- @ in pattern could be: @foo, @{foo}, @$foo, @'foo, @:foo.
+ @ in pattern could be: @foo, @{foo}, @$foo, @'foo, @::foo.
$ in pattern could be $foo or could be tail anchor. Assumption:
it's a tail anchor if $ is the last thing in the string, or if it's
else
#endif
for (i = min; i <= max; i++)
- *d++ = i;
+ *d++ = (char)i;
/* mark the range as done, and continue */
dorange = FALSE;
}
/* check for embedded arrays
- (@foo, @:foo, @'foo, @{foo}, @$foo, @+, @-)
+ (@foo, @::foo, @'foo, @{foo}, @$foo, @+, @-)
*/
else if (*s == '@' && s[1]
&& (isALNUM_lazy_if(s+1,UTF) || strchr(":'{$+-", s[1])))
while (src >= (U8 *)SvPVX(sv)) {
if (!NATIVE_IS_INVARIANT(*src)) {
U8 ch = NATIVE_TO_ASCII(*src);
- *dst-- = UTF8_EIGHT_BIT_LO(ch);
- *dst-- = UTF8_EIGHT_BIT_HI(ch);
+ *dst-- = (U8)UTF8_EIGHT_BIT_LO(ch);
+ *dst-- = (U8)UTF8_EIGHT_BIT_HI(ch);
}
else {
*dst-- = *src;
e = s - 1;
goto cont_scan;
}
+ if (e > s + 2 && s[1] == 'U' && s[2] == '+') {
+ /* \N{U+...} */
+ I32 flags = PERL_SCAN_ALLOW_UNDERSCORES |
+ PERL_SCAN_DISALLOW_PREFIX;
+ s += 3;
+ len = e - s;
+ uv = grok_hex(s, &len, &flags, NULL);
+ s = e + 1;
+ goto NUM_ESCAPE_INSERT;
+ }
res = newSVpvn(s + 1, e - s - 1);
res = new_constant( Nullch, 0, "charnames",
res, Nullsv, "\\N{...}" );
*d = '\0';
sv_utf8_upgrade(sv);
/* this just broke our allocation above... */
- SvGROW(sv, send - start);
+ SvGROW(sv, (STRLEN)(send - start));
d = SvPVX(sv) + SvCUR(sv);
has_utf8 = TRUE;
}
- if (len > e - s + 4) { /* I _guess_ 4 is \N{} --jhi */
+ if (len > (STRLEN)(e - s + 4)) { /* I _guess_ 4 is \N{} --jhi */
char *odest = SvPVX(sv);
SvGROW(sv, (SvLEN(sv) + len - (e - s + 4)));
* Method if it's "foo $bar"
* Not a method if it's really "print foo $bar"
* Method if it's really "foo package::" (interpreted as package->foo)
- * Not a method if bar is known to be a subroutne ("sub bar; foo bar")
+ * Not a method if bar is known to be a subroutine ("sub bar; foo bar")
* Not a method if bar is a filehandle or package, but is quoted with
* =>
*/
int old_len = SvCUR(buf_sv) ;
/* ensure buf_sv is large enough */
- SvGROW(buf_sv, old_len + maxlen) ;
+ SvGROW(buf_sv, (STRLEN)(old_len + maxlen)) ;
if ((len = PerlIO_read(PL_rsfp, SvPVX(buf_sv) + old_len, maxlen)) <= 0){
if (PerlIO_error(PL_rsfp))
return -1; /* error */
"### Saw case modifier at '%s'\n", PL_bufptr); });
s = PL_bufptr + 1;
if (strnEQ(s, "L\\u", 3) || strnEQ(s, "U\\l", 3))
- tmp = *s, *s = s[2], s[2] = tmp; /* misordered... */
+ tmp = *s, *s = s[2], s[2] = (char)tmp; /* misordered... */
if (strchr("LU", *s) &&
(strchr(PL_lex_casestack, 'L') || strchr(PL_lex_casestack, 'U')))
{
if (!PL_preprocess)
bof = PerlIO_tell(PL_rsfp) == SvCUR(PL_linestr);
#else
- bof = PerlIO_tell(PL_rsfp) == SvCUR(PL_linestr);
+ bof = PerlIO_tell(PL_rsfp) == (Off_t)SvCUR(PL_linestr);
#endif
if (bof) {
PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
sv_setpvn(x, ipath, ipathend - ipath);
SvSETMAGIC(x);
}
+ else {
+ STRLEN blen;
+ STRLEN llen;
+ char *bstart = SvPV(CopFILESV(PL_curcop),blen);
+ char *lstart = SvPV(x,llen);
+ if (llen < blen) {
+ bstart += blen - llen;
+ if (strnEQ(bstart, lstart, llen) && bstart[-1] == '/') {
+ sv_setpvn(x, ipath, ipathend - ipath);
+ SvSETMAGIC(x);
+ }
+ }
+ }
TAINT_NOT; /* $^X is always tainted, but that's OK */
}
#endif /* ARG_ZERO_IS_SCRIPT */
break;
}
if (ftst) {
- PL_last_lop_op = ftst;
+ PL_last_lop_op = (OPCODE)ftst;
DEBUG_T( { PerlIO_printf(Perl_debug_log,
"### Saw file test %c\n", (int)ftst);
} );
switch (tmp) {
case KEY_or:
case KEY_and:
+ case KEY_err:
case KEY_for:
case KEY_unless:
case KEY_if:
break; /* require real whitespace or :'s */
}
tmp = (PL_expect == XOPERATOR ? '=' : '{'); /*'}(' for vi */
- if (*s != ';' && *s != tmp && (tmp != '=' || *s != ')')) {
+ if (*s != ';' && *s != '}' && *s != tmp && (tmp != '=' || *s != ')')) {
char q = ((*s == '\'') ? '"' : '\'');
/* If here for an expression, and parsed no attrs, back off. */
if (tmp == '=' && !attrs) {
PL_expect = XTERM; /* e.g. print $fh 3 */
else if (*s == '.' && isDIGIT(s[1]))
PL_expect = XTERM; /* e.g. print $fh .3 */
- else if (strchr("/?-+", *s) && !isSPACE(s[1]) && s[1] != '=')
- PL_expect = XTERM; /* e.g. print $fh -1 */
+ else if (strchr("?-+", *s) && !isSPACE(s[1]) && s[1] != '=')
+ PL_expect = XTERM; /* e.g. print $fh -1 */
+ else if (*s == '/') {
+ if(s[1] == '/') {
+ PL_expect=XOPERATOR;
+ }
+ else {
+ PL_expect=XTERM;
+ }
+ }
else if (*s == '<' && s[1] == '<' && !isSPACE(s[2]) && s[2] != '=')
PL_expect = XTERM; /* print $fh <<"EOF" */
}
PL_pending_ident = '@';
TERM('@');
- case '/': /* may either be division or pattern */
- case '?': /* may either be conditional or pattern */
- if (PL_expect != XOPERATOR) {
- /* Disable warning on "study /blah/" */
- if (PL_oldoldbufptr == PL_last_uni
- && (*PL_last_uni != 's' || s - PL_last_uni < 5
- || memNE(PL_last_uni, "study", 5)
- || isALNUM_lazy_if(PL_last_uni+5,UTF)))
- check_uni();
- s = scan_pat(s,OP_MATCH);
- TERM(sublex_start());
- }
- tmp = *s++;
- if (tmp == '/')
- Mop(OP_DIVIDE);
- OPERATOR(tmp);
+ case '/': /* may be division, defined-or, or pattern */
+ case '?': /* may either be conditional or pattern */
+ if(PL_expect == XOPERATOR) {
+ tmp = *s++;
+ if(tmp == '?') {
+ OPERATOR('?');
+ }
+ else {
+ tmp = *s++;
+ if(tmp == '/') {
+ /* A // operator. */
+ AOPERATOR(DORDOR);
+ }
+ else {
+ s--;
+ Mop(OP_DIVIDE);
+ }
+ }
+ }
+ else {
+ /* Disable warning on "study /blah/" */
+ if (PL_oldoldbufptr == PL_last_uni
+ && (*PL_last_uni != 's' || s - PL_last_uni < 5
+ || memNE(PL_last_uni, "study", 5)
+ || isALNUM_lazy_if(PL_last_uni+5,UTF)
+ ))
+ check_uni();
+ s = scan_pat(s,OP_MATCH);
+ TERM(sublex_start());
+ }
case '.':
if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack
CLINE;
yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
yylval.opval->op_private = OPpCONST_BARE;
+ /* UTF-8 package name? */
+ if (UTF && !IN_BYTES &&
+ is_utf8_string((U8*)SvPVX(sv), SvCUR(sv)))
+ SvUTF8_on(sv);
/* And if "Foo::", then that's what it certainly is. */
if (ckWARN(WARN_RESERVED)) {
if (lastchar != '-') {
for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
- if (!*d && strNE(PL_tokenbuf,"main"))
+ if (!*d && !gv_stashpv(PL_tokenbuf,FALSE))
Perl_warner(aTHX_ packWARN(WARN_RESERVED), PL_warn_reserved,
PL_tokenbuf);
}
case KEY_eof:
UNI(OP_EOF);
+ case KEY_err:
+ OPERATOR(DOROP);
+
case KEY_exp:
UNI(OP_EXP);
break;
case 3:
if (strEQ(d,"eof")) return -KEY_eof;
+ if (strEQ(d,"err")) return -KEY_err;
if (strEQ(d,"exp")) return -KEY_exp;
break;
case 4:
}
void
-Perl_pmflag(pTHX_ U16 *pmfl, int ch)
+Perl_pmflag(pTHX_ U32* pmfl, int ch)
{
if (ch == 'i')
*pmfl |= PMf_FOLD;
while (*s && strchr("iogcmsx", *s))
pmflag(&pm->op_pmflags,*s++);
}
+ /* issue a warning if /c is specified,but /g is not */
+ if (ckWARN(WARN_REGEXP) &&
+ (pm->op_pmflags & PMf_CONTINUE) && !(pm->op_pmflags & PMf_GLOBAL))
+ {
+ Perl_warner(aTHX_ packWARN(WARN_REGEXP), c_without_g);
+ }
+
pm->op_pmpermflags = pm->op_pmflags;
PL_lex_op = (OP*)pm;
break;
}
+ /* /c is not meaningful with s/// */
+ if (ckWARN(WARN_REGEXP) && (pm->op_pmflags & PMf_CONTINUE))
+ {
+ Perl_warner(aTHX_ packWARN(WARN_REGEXP), c_in_subst);
+ }
+
if (es) {
SV *repl;
PL_sublex_info.super_bufptr = s;
CopLINE_inc(PL_curcop);
}
if (s >= bufend) {
- CopLINE_set(PL_curcop, PL_multi_start);
+ CopLINE_set(PL_curcop, (line_t)PL_multi_start);
missingterm(PL_tokenbuf);
}
sv_setpvn(herewas,bufptr,d-bufptr+1);
CopLINE_inc(PL_curcop);
}
if (s >= PL_bufend) {
- CopLINE_set(PL_curcop, PL_multi_start);
+ CopLINE_set(PL_curcop, (line_t)PL_multi_start);
missingterm(PL_tokenbuf);
}
sv_setpvn(tmpstr,d+1,s-d);
while (s >= PL_bufend) { /* multiple line string? */
if (!outer ||
!(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
- CopLINE_set(PL_curcop, PL_multi_start);
+ CopLINE_set(PL_curcop, (line_t)PL_multi_start);
missingterm(PL_tokenbuf);
}
CopLINE_inc(PL_curcop);
if (!PL_rsfp ||
!(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
sv_free(sv);
- CopLINE_set(PL_curcop, PL_multi_start);
+ CopLINE_set(PL_curcop, (line_t)PL_multi_start);
return Nullch;
}
/* we read a line, so increment our line counter */
case 'v':
vstring:
sv = NEWSV(92,5); /* preallocate storage space */
- s = new_vstring(s,sv);
+ s = scan_vstring(s,sv);
break;
}
where = "at EOF";
else if (PL_bufptr > PL_oldoldbufptr && PL_bufptr - PL_oldoldbufptr < 200 &&
PL_oldoldbufptr != PL_oldbufptr && PL_oldbufptr != PL_bufptr) {
+ /*
+ Only for NetWare:
+ The code below is removed for NetWare because it abends/crashes on NetWare
+ when the script has error such as not having the closing quotes like:
+ if ($var eq "value)
+ Checking of white spaces is anyway done in NetWare code.
+ */
+#ifndef NETWARE
while (isSPACE(*PL_oldoldbufptr))
PL_oldoldbufptr++;
+#endif
context = PL_oldoldbufptr;
contlen = PL_bufptr - PL_oldoldbufptr;
}
else if (PL_bufptr > PL_oldbufptr && PL_bufptr - PL_oldbufptr < 200 &&
PL_oldbufptr != PL_bufptr) {
+ /*
+ Only for NetWare:
+ The code below is removed for NetWare because it abends/crashes on NetWare
+ when the script has error such as not having the closing quotes like:
+ if ($var eq "value)
+ Checking of white spaces is anyway done in NetWare code.
+ */
+#ifndef NETWARE
while (isSPACE(*PL_oldbufptr))
PL_oldbufptr++;
+#endif
context = PL_oldbufptr;
contlen = PL_bufptr - PL_oldbufptr;
}