X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=toke.c;h=d8cd2e5fae2d59632d694700aaca000642f583d1;hb=f19a12a3a65a1b840e4df1373a12eab6e50a8d5c;hp=12d91afa775f1b669ecd50d9162429a830e01b72;hpb=651b5b28673befa3f36a39b00591c15d5b30cca2;p=p5sagit%2Fp5-mst-13.2.git diff --git a/toke.c b/toke.c index 12d91af..d8cd2e5 100644 --- a/toke.c +++ b/toke.c @@ -1,7 +1,7 @@ /* toke.c * - * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -9,7 +9,9 @@ */ /* - * "It all comes from here, the stench and the peril." --Frodo + * 'It all comes from here, the stench and the peril.' --Frodo + * + * [p.719 of _The Lord of the Rings_, IV/ix: "Shelob's Lair"] */ /* @@ -23,7 +25,10 @@ #define PERL_IN_TOKE_C #include "perl.h" -#define yylval (PL_parser->yylval) +#define new_constant(a,b,c,d,e,f,g) \ + S_new_constant(aTHX_ a,b,STR_WITH_LEN(c),d,e,f, g) + +#define pl_yylval (PL_parser->yylval) /* YYINITDEPTH -- initial size of the parser's stacks. */ #define YYINITDEPTH 200 @@ -49,6 +54,25 @@ #define PL_pending_ident (PL_parser->pending_ident) #define PL_preambled (PL_parser->preambled) #define PL_sublex_info (PL_parser->sublex_info) +#define PL_linestr (PL_parser->linestr) +#define PL_expect (PL_parser->expect) +#define PL_copline (PL_parser->copline) +#define PL_bufptr (PL_parser->bufptr) +#define PL_oldbufptr (PL_parser->oldbufptr) +#define PL_oldoldbufptr (PL_parser->oldoldbufptr) +#define PL_linestart (PL_parser->linestart) +#define PL_bufend (PL_parser->bufend) +#define PL_last_uni (PL_parser->last_uni) +#define PL_last_lop (PL_parser->last_lop) +#define PL_last_lop_op (PL_parser->last_lop_op) +#define PL_lex_state (PL_parser->lex_state) +#define PL_rsfp (PL_parser->rsfp) +#define PL_rsfp_filters (PL_parser->rsfp_filters) +#define PL_in_my (PL_parser->in_my) +#define PL_in_my_stash (PL_parser->in_my_stash) +#define PL_tokenbuf (PL_parser->tokenbuf) +#define PL_multi_end (PL_parser->multi_end) +#define PL_error_count (PL_parser->error_count) #ifdef PERL_MAD # define PL_endwhite (PL_parser->endwhite) @@ -63,6 +87,13 @@ # define PL_thisstuff (PL_parser->thisstuff) # define PL_thistoken (PL_parser->thistoken) # define PL_thiswhite (PL_parser->thiswhite) +# define PL_thiswhite (PL_parser->thiswhite) +# define PL_nexttoke (PL_parser->nexttoke) +# define PL_curforce (PL_parser->curforce) +#else +# define PL_nexttoke (PL_parser->nexttoke) +# define PL_nexttype (PL_parser->nexttype) +# define PL_nextval (PL_parser->nextval) #endif static int @@ -71,7 +102,6 @@ S_pending_ident(pTHX); static const char ident_too_long[] = "Identifier too long"; static const char commaless_variable_list[] = "comma-less variable list"; -static void restore_rsfp(pTHX_ void *f); #ifndef PERL_NO_UTF16_FILTER static I32 utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen); static I32 utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen); @@ -199,7 +229,7 @@ static const char* const lex_state_names[] = { */ #ifdef DEBUGGING /* Serve -DT. */ -# define REPORT(retval) tokereport((I32)retval) +# define REPORT(retval) tokereport((I32)retval, &pl_yylval) #else # define REPORT(retval) (retval) #endif @@ -211,19 +241,19 @@ static const char* const lex_state_names[] = { #define PRETERMBLOCK(retval) return (PL_expect = XTERMBLOCK,PL_bufptr = s, REPORT(retval)) #define PREREF(retval) return (PL_expect = XREF,PL_bufptr = s, REPORT(retval)) #define TERM(retval) return (CLINE, PL_expect = XOPERATOR, PL_bufptr = s, REPORT(retval)) -#define LOOPX(f) return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)LOOPEX)) -#define FTST(f) return (yylval.ival=f, PL_expect=XTERMORDORDOR, PL_bufptr=s, REPORT((int)UNIOP)) -#define FUN0(f) return (yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0)) -#define FUN1(f) return (yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC1)) -#define BOop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITOROP))) -#define BAop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITANDOP))) -#define SHop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)SHIFTOP))) -#define PWop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)POWOP))) -#define PMop(f) return(yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MATCHOP)) -#define Aop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)ADDOP))) -#define Mop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MULOP))) -#define Eop(f) return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)EQOP)) -#define Rop(f) return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)RELOP)) +#define LOOPX(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)LOOPEX)) +#define FTST(f) return (pl_yylval.ival=f, PL_expect=XTERMORDORDOR, PL_bufptr=s, REPORT((int)UNIOP)) +#define FUN0(f) return (pl_yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0)) +#define FUN1(f) return (pl_yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC1)) +#define BOop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITOROP))) +#define BAop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITANDOP))) +#define SHop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)SHIFTOP))) +#define PWop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)POWOP))) +#define PMop(f) return(pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MATCHOP)) +#define Aop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)ADDOP))) +#define Mop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MULOP))) +#define Eop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)EQOP)) +#define Rop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)RELOP)) /* This bit of chicanery makes a unary function followed by * a parenthesis into a function with one argument, highest precedence. @@ -231,7 +261,7 @@ static const char* const lex_state_names[] = { * operator (such as C). */ #define UNI2(f,x) { \ - yylval.ival = f; \ + pl_yylval.ival = f; \ PL_expect = x; \ PL_bufptr = s; \ PL_last_uni = PL_oldbufptr; \ @@ -245,7 +275,7 @@ static const char* const lex_state_names[] = { #define UNIDOR(f) UNI2(f,XTERMORDORDOR) #define UNIBRACK(f) { \ - yylval.ival = f; \ + pl_yylval.ival = f; \ PL_bufptr = s; \ PL_last_uni = PL_oldbufptr; \ if (*s == '(') \ @@ -255,15 +285,15 @@ static const char* const lex_state_names[] = { } /* grandfather return to old style */ -#define OLDLOP(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LSTOP) +#define OLDLOP(f) return(pl_yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LSTOP) #ifdef DEBUGGING -/* how to interpret the yylval associated with the token */ +/* how to interpret the pl_yylval associated with the token */ enum token_type { TOKENTYPE_NONE, TOKENTYPE_IVAL, - TOKENTYPE_OPNUM, /* yylval.ival contains an opcode number */ + TOKENTYPE_OPNUM, /* pl_yylval.ival contains an opcode number */ TOKENTYPE_PVAL, TOKENTYPE_OPVAL, TOKENTYPE_GVVAL @@ -340,15 +370,19 @@ static struct debug_tokens { { WHEN, TOKENTYPE_IVAL, "WHEN" }, { WHILE, TOKENTYPE_IVAL, "WHILE" }, { WORD, TOKENTYPE_OPVAL, "WORD" }, + { YADAYADA, TOKENTYPE_IVAL, "YADAYADA" }, { 0, TOKENTYPE_NONE, NULL } }; -/* dump the returned token in rv, plus any optional arg in yylval */ +/* dump the returned token in rv, plus any optional arg in pl_yylval */ STATIC int -S_tokereport(pTHX_ I32 rv) +S_tokereport(pTHX_ I32 rv, const YYSTYPE* lvalp) { dVAR; + + PERL_ARGS_ASSERT_TOKEREPORT; + if (DEBUG_T_TEST) { const char *name = NULL; enum token_type type = TOKENTYPE_NONE; @@ -375,22 +409,22 @@ S_tokereport(pTHX_ I32 rv) case TOKENTYPE_GVVAL: /* doesn't appear to be used */ break; case TOKENTYPE_IVAL: - Perl_sv_catpvf(aTHX_ report, "(ival=%"IVdf")", (IV)yylval.ival); + Perl_sv_catpvf(aTHX_ report, "(ival=%"IVdf")", (IV)lvalp->ival); break; case TOKENTYPE_OPNUM: Perl_sv_catpvf(aTHX_ report, "(ival=op_%s)", - PL_op_name[yylval.ival]); + PL_op_name[lvalp->ival]); break; case TOKENTYPE_PVAL: - Perl_sv_catpvf(aTHX_ report, "(pval=\"%s\")", yylval.pval); + Perl_sv_catpvf(aTHX_ report, "(pval=\"%s\")", lvalp->pval); break; case TOKENTYPE_OPVAL: - if (yylval.opval) { + if (lvalp->opval) { Perl_sv_catpvf(aTHX_ report, "(opval=op_%s)", - PL_op_name[yylval.opval->op_type]); - if (yylval.opval->op_type == OP_CONST) { + PL_op_name[lvalp->opval->op_type]); + if (lvalp->opval->op_type == OP_CONST) { Perl_sv_catpvf(aTHX_ report, " %s", - SvPEEK(cSVOPx_sv(yylval.opval))); + SvPEEK(cSVOPx_sv(lvalp->opval))); } } @@ -407,9 +441,12 @@ S_tokereport(pTHX_ I32 rv) /* print the buffer with suitable escapes */ STATIC void -S_printbuf(pTHX_ const char* fmt, const char* s) +S_printbuf(pTHX_ const char *const fmt, const char *const s) { SV* const tmp = newSVpvs(""); + + PERL_ARGS_ASSERT_PRINTBUF; + PerlIO_printf(Perl_debug_log, fmt, pv_display(tmp, s, strlen(s), 0, 60)); SvREFCNT_dec(tmp); } @@ -430,11 +467,11 @@ S_ao(pTHX_ int toketype) if (*PL_bufptr == '=') { PL_bufptr++; if (toketype == ANDAND) - yylval.ival = OP_ANDASSIGN; + pl_yylval.ival = OP_ANDASSIGN; else if (toketype == OROR) - yylval.ival = OP_ORASSIGN; + pl_yylval.ival = OP_ORASSIGN; else if (toketype == DORDOR) - yylval.ival = OP_DORASSIGN; + pl_yylval.ival = OP_DORASSIGN; toketype = ASSIGNOP; } return toketype; @@ -454,12 +491,14 @@ S_ao(pTHX_ int toketype) */ STATIC void -S_no_op(pTHX_ const char *what, char *s) +S_no_op(pTHX_ const char *const what, char *s) { dVAR; char * const oldbp = PL_bufptr; const bool is_first = (PL_oldbufptr == PL_linestart); + PERL_ARGS_ASSERT_NO_OP; + if (!s) s = oldbp; else @@ -507,13 +546,7 @@ S_missingterm(pTHX_ char *s) if (nl) *nl = '\0'; } - else if ( -#ifdef EBCDIC - iscntrl(PL_multi_close) -#else - PL_multi_close < 32 || PL_multi_close == 127 -#endif - ) { + else if (isCNTRL(PL_multi_close)) { *tmpbuf = '^'; tmpbuf[1] = (char)toCTRL(PL_multi_close); tmpbuf[2] = '\0'; @@ -531,17 +564,24 @@ S_missingterm(pTHX_ char *s) #define FEATURE_IS_ENABLED(name) \ ((0 != (PL_hints & HINT_LOCALIZE_HH)) \ && S_feature_is_enabled(aTHX_ STR_WITH_LEN(name))) +/* The longest string we pass in. */ +#define MAX_FEATURE_LEN (sizeof("switch")-1) + /* * S_feature_is_enabled * Check whether the named feature is enabled. */ STATIC bool -S_feature_is_enabled(pTHX_ const char *name, STRLEN namelen) +S_feature_is_enabled(pTHX_ const char *const name, STRLEN namelen) { dVAR; HV * const hinthv = GvHV(PL_hintgv); - char he_name[32] = "feature_"; - (void) my_strlcpy(&he_name[8], name, 24); + char he_name[8 + MAX_FEATURE_LEN] = "feature_"; + + PERL_ARGS_ASSERT_FEATURE_IS_ENABLED; + + assert(namelen <= MAX_FEATURE_LEN); + memcpy(&he_name[8], name, namelen); return (hinthv && hv_exists(hinthv, he_name, 8 + namelen)); } @@ -551,14 +591,16 @@ S_feature_is_enabled(pTHX_ const char *name, STRLEN namelen) */ void -Perl_deprecate(pTHX_ const char *s) +Perl_deprecate(pTHX_ const char *const s) { + PERL_ARGS_ASSERT_DEPRECATE; + if (ckWARN(WARN_DEPRECATED)) Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), "Use of %s is deprecated", s); } void -Perl_deprecate_old(pTHX_ const char *s) +Perl_deprecate_old(pTHX_ const char *const s) { /* This function should NOT be called for any new deprecated warnings */ /* Use Perl_deprecate instead */ @@ -568,6 +610,8 @@ Perl_deprecate_old(pTHX_ const char *s) /* live under the "syntax" category. It is now a top-level category */ /* in its own right. */ + PERL_ARGS_ASSERT_DEPRECATE_OLD; + if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Use of %s is deprecated", s); @@ -584,6 +628,9 @@ strip_return(SV *sv) { register const char *s = SvPVX_const(sv); register const char * const e = s + SvCUR(sv); + + PERL_ARGS_ASSERT_STRIP_RETURN; + /* outer loop optimized to do nothing if there are no CR-LFs */ while (s < e) { if (*s++ == '\r' && *s == '\n') { @@ -615,21 +662,30 @@ S_cr_textfilter(pTHX_ int idx, SV *sv, int maxlen) /* * Perl_lex_start + * * Create a parser object and initialise its parser and lexer fields + * + * rsfp is the opened file handle to read from (if any), + * + * line holds any initial content already read from the file (or in + * the case of no file, such as an eval, the whole contents); + * + * new_filter indicates that this is a new file and it shouldn't inherit + * the filters from the current parser (ie require). */ void -Perl_lex_start(pTHX_ SV *line) +Perl_lex_start(pTHX_ SV *line, PerlIO *rsfp, bool new_filter) { dVAR; const char *s = NULL; STRLEN len; - yy_parser *parser; + yy_parser *parser, *oparser; /* create and initialise a parser */ Newxz(parser, 1, yy_parser); - parser->old_parser = PL_parser; + parser->old_parser = oparser = PL_parser; PL_parser = parser; Newx(parser->stack, YYINITDEPTH, yy_stack_frame); @@ -642,77 +698,50 @@ Perl_lex_start(pTHX_ SV *line) /* on scope exit, free this parser and restore any outer one */ SAVEPARSER(parser); + parser->saved_curcop = PL_curcop; /* initialise lexer state */ - SAVEI8(PL_lex_state); #ifdef PERL_MAD - if (PL_lex_state == LEX_KNOWNEXT) { - I32 toke = parser->old_parser->lasttoke; - while (--toke >= 0) { - SAVEI32(PL_nexttoke[toke].next_type); - SAVEVPTR(PL_nexttoke[toke].next_val); - if (PL_madskills) - SAVEVPTR(PL_nexttoke[toke].next_mad); - } - } - SAVEI32(PL_curforce); - PL_curforce = -1; + parser->curforce = -1; #else - if (PL_lex_state == LEX_KNOWNEXT) { - I32 toke = PL_nexttoke; - while (--toke >= 0) { - SAVEI32(PL_nexttype[toke]); - SAVEVPTR(PL_nextval[toke]); - } - SAVEI32(PL_nexttoke); - } + parser->nexttoke = 0; #endif - SAVECOPLINE(PL_curcop); - SAVEPPTR(PL_bufptr); - SAVEPPTR(PL_bufend); - SAVEPPTR(PL_oldbufptr); - SAVEPPTR(PL_oldoldbufptr); - SAVEPPTR(PL_last_lop); - SAVEPPTR(PL_last_uni); - SAVEPPTR(PL_linestart); - SAVESPTR(PL_linestr); - SAVEDESTRUCTOR_X(restore_rsfp, PL_rsfp); - SAVEI8(PL_expect); + parser->error_count = oparser ? oparser->error_count : 0; + parser->copline = NOLINE; + parser->lex_state = LEX_NORMAL; + parser->expect = XSTATE; + parser->rsfp = rsfp; + parser->rsfp_filters = (new_filter || !oparser) ? newAV() + : MUTABLE_AV(SvREFCNT_inc(oparser->rsfp_filters)); - PL_copline = NOLINE; - PL_lex_state = LEX_NORMAL; - PL_expect = XSTATE; Newx(parser->lex_brackstack, 120, char); Newx(parser->lex_casestack, 12, char); *parser->lex_casestack = '\0'; -#ifndef PERL_MAD - PL_nexttoke = 0; -#endif if (line) { s = SvPV_const(line, len); } else { len = 0; } + if (!len) { - PL_linestr = newSVpvs("\n;"); + parser->linestr = newSVpvs("\n;"); } else if (SvREADONLY(line) || s[len-1] != ';') { - PL_linestr = newSVsv(line); + parser->linestr = newSVsv(line); if (s[len-1] != ';') - sv_catpvs(PL_linestr, "\n;"); + sv_catpvs(parser->linestr, "\n;"); } else { SvTEMP_off(line); SvREFCNT_inc_simple_void_NN(line); - PL_linestr = line; - } - /* PL_linestr needs to survive until end of scope, not just the next - FREETMPS. See changes 17505 and 17546 which fixed the symptoms only. */ - SAVEFREESV(PL_linestr); - PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = SvPVX(PL_linestr); - PL_bufend = PL_bufptr + SvCUR(PL_linestr); - PL_last_lop = PL_last_uni = NULL; - PL_rsfp = 0; + parser->linestr = line; + } + parser->oldoldbufptr = + parser->oldbufptr = + parser->bufptr = + parser->linestart = SvPVX(parser->linestr); + parser->bufend = parser->bufptr + SvCUR(parser->linestr); + parser->last_lop = parser->last_uni = NULL; } @@ -721,6 +750,18 @@ Perl_lex_start(pTHX_ SV *line) void Perl_parser_free(pTHX_ const yy_parser *parser) { + PERL_ARGS_ASSERT_PARSER_FREE; + + PL_curcop = parser->saved_curcop; + SvREFCNT_dec(parser->linestr); + + if (parser->rsfp == PerlIO_stdin()) + PerlIO_clearerr(parser->rsfp); + else if (parser->rsfp && (!parser->old_parser || + (parser->old_parser && parser->rsfp != parser->old_parser->rsfp))) + PerlIO_close(parser->rsfp); + SvREFCNT_dec(parser->rsfp_filters); + Safefree(parser->stack); Safefree(parser->lex_brackstack); Safefree(parser->lex_casestack); @@ -760,6 +801,8 @@ S_incline(pTHX_ const char *s) const char *n; const char *e; + PERL_ARGS_ASSERT_INCLINE; + CopLINE_inc(PL_curcop); if (*s++ != '#') return; @@ -801,8 +844,18 @@ S_incline(pTHX_ const char *s) if (t - s > 0) { const STRLEN len = t - s; #ifndef USE_ITHREADS - const char * const cf = CopFILE(PL_curcop); - STRLEN tmplen = cf ? strlen(cf) : 0; + SV *const temp_sv = CopFILESV(PL_curcop); + const char *cf; + STRLEN tmplen; + + if (temp_sv) { + cf = SvPVX(temp_sv); + tmplen = SvCUR(temp_sv); + } else { + cf = NULL; + tmplen = 0; + } + if (tmplen > 7 && strnEQ(cf, "(eval ", 6)) { /* must copy *{"::_<(eval N)[oldfilename:L]"} * to *{"::_mad_key == '^') { (*where)->mad_key = slot; - sv_free((*where)->mad_val); + sv_free(MUTABLE_SV(((*where)->mad_val))); (*where)->mad_val = (void*)sv; } else @@ -1290,6 +1353,12 @@ STATIC void S_force_next(pTHX_ I32 type) { dVAR; +#ifdef DEBUGGING + if (DEBUG_T_TEST) { + PerlIO_printf(Perl_debug_log, "### forced token:\n"); + tokereport(type, &NEXTVAL_NEXTTOKE); + } +#endif #ifdef PERL_MAD if (PL_curforce < 0) start_force(PL_lasttoke); @@ -1311,12 +1380,12 @@ S_force_next(pTHX_ I32 type) } STATIC SV * -S_newSV_maybe_utf8(pTHX_ const char *start, STRLEN len) +S_newSV_maybe_utf8(pTHX_ const char *const start, STRLEN len) { dVAR; - SV * const sv = newSVpvn(start,len); - if (UTF && !IN_BYTES && is_utf8_string((const U8*)start, len)) - SvUTF8_on(sv); + SV * const sv = newSVpvn_utf8(start, len, + UTF && !IN_BYTES + && is_utf8_string((const U8*)start, len)); return sv; } @@ -1344,6 +1413,8 @@ S_force_word(pTHX_ register char *start, int token, int check_keyword, int allow register char *s; STRLEN len; + PERL_ARGS_ASSERT_FORCE_WORD; + start = SKIPSPACE1(start); s = start; if (isIDFIRST_lazy_if(s,UTF) || @@ -1388,6 +1459,9 @@ STATIC void S_force_ident(pTHX_ register const char *s, int kind) { dVAR; + + PERL_ARGS_ASSERT_FORCE_IDENT; + if (*s) { const STRLEN len = strlen(s); OP* const o = (OP*)newSVOP(OP_CONST, 0, newSVpvn(s, len)); @@ -1420,6 +1494,9 @@ Perl_str_to_version(pTHX_ SV *sv) const char *start = SvPV_const(sv,len); const char * const end = start + len; const bool utf = SvUTF8(sv) ? TRUE : FALSE; + + PERL_ARGS_ASSERT_STR_TO_VERSION; + while (start < end) { STRLEN skip; UV n; @@ -1454,6 +1531,8 @@ S_force_version(pTHX_ char *s, int guessing) I32 startoff = s - SvPVX(PL_linestr); #endif + PERL_ARGS_ASSERT_FORCE_VERSION; + s = SKIPSPACE1(s); d = s; @@ -1470,8 +1549,8 @@ S_force_version(pTHX_ char *s, int guessing) #endif if (*d == ';' || isSPACE(*d) || *d == '}' || !*d) { SV *ver; - s = scan_num(s, &yylval); - version = yylval.opval; + s = scan_num(s, &pl_yylval); + version = pl_yylval.opval; ver = cSVOPx(version)->op_sv; if (SvPOK(ver) && !SvNIOK(ver)) { SvUPGRADE(ver, SVt_PVNV); @@ -1524,6 +1603,8 @@ S_tokeq(pTHX_ SV *sv) STRLEN len = 0; SV *pv = sv; + PERL_ARGS_ASSERT_TOKEQ; + if (!SvLEN(sv)) goto finish; @@ -1537,9 +1618,7 @@ S_tokeq(pTHX_ SV *sv) goto finish; d = s; if ( PL_hints & HINT_NEW_STRING ) { - pv = sv_2mortal(newSVpvn(SvPVX_const(pv), len)); - if (SvUTF8(sv)) - SvUTF8_on(pv); + pv = newSVpvn_flags(SvPVX_const(pv), len, SVs_TEMP | SvUTF8(sv)); } while (s < send) { if (*s == '\\') { @@ -1552,7 +1631,7 @@ S_tokeq(pTHX_ SV *sv) SvCUR_set(sv, d - SvPVX_const(sv)); finish: if ( PL_hints & HINT_NEW_STRING ) - return new_constant(NULL, 0, "q", sv, pv, "q"); + return new_constant(NULL, 0, "q", sv, pv, "q", 1); return sv; } @@ -1574,10 +1653,10 @@ S_tokeq(pTHX_ SV *sv) /* * S_sublex_start - * Assumes that yylval.ival is the op we're creating (e.g. OP_LCFIRST). + * Assumes that pl_yylval.ival is the op we're creating (e.g. OP_LCFIRST). * * Pattern matching will set PL_lex_op to the pattern-matching op to - * make (we return THING if yylval.ival is OP_NULL, PMFUNC otherwise). + * make (we return THING if pl_yylval.ival is OP_NULL, PMFUNC otherwise). * * OP_CONST and OP_READLINE are easy--just make the new op and return. * @@ -1592,10 +1671,10 @@ STATIC I32 S_sublex_start(pTHX) { dVAR; - register const I32 op_type = yylval.ival; + register const I32 op_type = pl_yylval.ival; if (op_type == OP_NULL) { - yylval.opval = PL_lex_op; + pl_yylval.opval = PL_lex_op; PL_lex_op = NULL; return THING; } @@ -1606,13 +1685,11 @@ S_sublex_start(pTHX) /* Overloaded constants, nothing fancy: Convert to SVt_PV: */ STRLEN len; const char * const p = SvPV_const(sv, len); - SV * const nsv = newSVpvn(p, len); - if (SvUTF8(sv)) - SvUTF8_on(nsv); + SV * const nsv = newSVpvn_flags(p, len, SvUTF8(sv)); SvREFCNT_dec(sv); sv = nsv; } - yylval.opval = (OP*)newSVOP(op_type, 0, sv); + pl_yylval.opval = (OP*)newSVOP(op_type, 0, sv); PL_lex_stuff = NULL; /* Allow // "foo" */ if (op_type == OP_READLINE) @@ -1622,20 +1699,20 @@ S_sublex_start(pTHX) else if (op_type == OP_BACKTICK && PL_lex_op) { /* readpipe() vas overriden */ cSVOPx(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first->op_sibling)->op_sv = tokeq(PL_lex_stuff); - yylval.opval = PL_lex_op; + pl_yylval.opval = PL_lex_op; PL_lex_op = NULL; PL_lex_stuff = NULL; return THING; } PL_sublex_info.super_state = PL_lex_state; - PL_sublex_info.sub_inwhat = op_type; + PL_sublex_info.sub_inwhat = (U16)op_type; PL_sublex_info.sub_op = PL_lex_op; PL_lex_state = LEX_INTERPPUSH; PL_expect = XTERM; if (PL_lex_op) { - yylval.opval = PL_lex_op; + pl_yylval.opval = PL_lex_op; PL_lex_op = NULL; return PMFUNC; } @@ -1664,7 +1741,7 @@ S_sublex_push(pTHX) SAVEI32(PL_lex_starts); SAVEI8(PL_lex_state); SAVEVPTR(PL_lex_inpat); - SAVEI8(PL_lex_inwhat); + SAVEI16(PL_lex_inwhat); SAVECOPLINE(PL_curcop); SAVEPPTR(PL_bufptr); SAVEPPTR(PL_bufend); @@ -1719,7 +1796,7 @@ S_sublex_done(pTHX) if (SvUTF8(PL_linestr)) SvUTF8_on(sv); PL_expect = XOPERATOR; - yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); return THING; } @@ -1765,7 +1842,7 @@ S_sublex_done(pTHX) PL_thiswhite = 0; } if (PL_thistoken) - sv_setpvn(PL_thistoken,"",0); + sv_setpvs(PL_thistoken,""); else PL_realtokenstart = -1; } @@ -1792,7 +1869,7 @@ S_sublex_done(pTHX) Returns a pointer to the character scanned up to. If this is advanced from the start pointer supplied (i.e. if anything was successfully parsed), will leave an OP for the substring scanned - in yylval. Caller must intuit reason for not parsing further + in pl_yylval. Caller must intuit reason for not parsing further by looking at the next characters herself. In patterns: @@ -1876,6 +1953,8 @@ S_scan_const(pTHX_ char *start) bool native_range = TRUE; /* turned to FALSE if the first endpoint is Unicode. */ #endif + PERL_ARGS_ASSERT_SCAN_CONST; + if (PL_lex_inwhat == OP_TRANS && PL_sublex_info.sub_op) { /* If we are doing a trans and we know we want UTF8 set expectation */ has_utf8 = PL_sublex_info.sub_op->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF); @@ -2090,8 +2169,13 @@ S_scan_const(pTHX_ char *start) else if (*s == '$') { if (!PL_lex_inpat) /* not a regexp, so $ must be var */ break; - if (s + 1 < send && !strchr("()| \r\n\t", s[1])) + if (s + 1 < send && !strchr("()| \r\n\t", s[1])) { + if (s[1] == '\\' && ckWARN(WARN_AMBIGUOUS)) { + Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS), + "Possible unintended interpolation of $\\ in regex"); + } break; /* in regexp, $ might be tail anchor */ + } } /* End of else if chain - OP_TRANS rejoin rest */ @@ -2257,7 +2341,6 @@ S_scan_const(pTHX_ char *start) SV *res; STRLEN len; const char *str; - SV *type; if (!e) { yyerror("Missing right brace on \\N{}"); @@ -2278,10 +2361,8 @@ S_scan_const(pTHX_ char *start) goto NUM_ESCAPE_INSERT; } res = newSVpvn(s + 1, e - s - 1); - type = newSVpvn(s - 2,e - s + 3); res = new_constant( NULL, 0, "charnames", - res, NULL, SvPVX(type) ); - SvREFCNT_dec(type); + res, NULL, s - 2, e - s + 3 ); if (has_utf8) sv_utf8_upgrade(res); str = SvPV_const(res,len); @@ -2434,19 +2515,29 @@ S_scan_const(pTHX_ char *start) SvPV_shrink_to_cur(sv); } - /* return the substring (via yylval) only if we parsed anything */ + /* return the substring (via pl_yylval) only if we parsed anything */ if (s > PL_bufptr) { - if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) ) - sv = new_constant(start, s - start, - (const char *)(PL_lex_inpat ? "qr" : "q"), - sv, NULL, - (const char *) - (( PL_lex_inwhat == OP_TRANS - ? "tr" - : ( (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat) - ? "s" - : "qq")))); - yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); + if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) ) { + const char *const key = PL_lex_inpat ? "qr" : "q"; + const STRLEN keylen = PL_lex_inpat ? 2 : 1; + const char *type; + STRLEN typelen; + + if (PL_lex_inwhat == OP_TRANS) { + type = "tr"; + typelen = 2; + } else if (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat) { + type = "s"; + typelen = 1; + } else { + type = "qq"; + typelen = 2; + } + + sv = S_new_constant(aTHX_ start, s - start, key, keylen, sv, NULL, + type, typelen); + } + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); } else SvREFCNT_dec(sv); return s; @@ -2477,6 +2568,9 @@ STATIC int S_intuit_more(pTHX_ register char *s) { dVAR; + + PERL_ARGS_ASSERT_INTUIT_MORE; + if (PL_lex_brackets) return TRUE; if (*s == '-' && s[1] == '>' && (s[2] == '[' || s[2] == '{')) @@ -2642,6 +2736,8 @@ S_intuit_method(pTHX_ char *start, GV *gv, CV *cv) int soff; #endif + PERL_ARGS_ASSERT_INTUIT_METHOD; + if (gv) { if (SvTYPE(gv) == SVt_PVGV && GvIO(gv)) return 0; @@ -2718,29 +2814,6 @@ S_intuit_method(pTHX_ char *start, GV *gv, CV *cv) return 0; } -/* - * S_incl_perldb - * Return a string of Perl code to load the debugger. If PERL5DB - * is set, it will return the contents of that, otherwise a - * compile-time require of perl5db.pl. - */ - -STATIC const char* -S_incl_perldb(pTHX) -{ - dVAR; - if (PL_perldb) { - const char * const pdb = PerlEnv_getenv("PERL5DB"); - - if (pdb) - return pdb; - SETERRNO(0,SS_NORMAL); - return "BEGIN { require 'perl5db.pl' }"; - } - return ""; -} - - /* Encoded script support. filter_add() effectively inserts a * 'pre-processing' function into the current source input stream. * Note that the filter function only applies to the current source file @@ -2765,6 +2838,9 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv) if (!funcp) return NULL; + if (!PL_parser) + return NULL; + if (!PL_rsfp_filters) PL_rsfp_filters = newAV(); if (!datasv) @@ -2788,11 +2864,13 @@ Perl_filter_del(pTHX_ filter_t funcp) dVAR; SV *datasv; + PERL_ARGS_ASSERT_FILTER_DEL; + #ifdef DEBUGGING DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p", FPTR2DPTR(void*, funcp))); #endif - if (!PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0) + if (!PL_parser || !PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0) return; /* if filter is on top of stack (usual case) just pop it off */ datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters)); @@ -2828,7 +2906,9 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen) #endif : maxlen; - if (!PL_rsfp_filters) + PERL_ARGS_ASSERT_FILTER_READ; + + if (!PL_parser || !PL_rsfp_filters) return -1; if (idx > AvFILLp(PL_rsfp_filters)) { /* Any more filters? */ /* Provide a default input filter to make life easy. */ @@ -2883,6 +2963,9 @@ STATIC char * S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append) { dVAR; + + PERL_ARGS_ASSERT_FILTER_GETS; + #ifdef PERL_CR_FILTER if (!PL_rsfp_filters) { filter_add(S_cr_textfilter,NULL); @@ -2901,11 +2984,13 @@ S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append) } STATIC HV * -S_find_in_my_stash(pTHX_ const char *pkgname, I32 len) +S_find_in_my_stash(pTHX_ const char *pkgname, STRLEN len) { dVAR; GV *gv; + PERL_ARGS_ASSERT_FIND_IN_MY_STASH; + if (len == 11 && *pkgname == '_' && strEQ(pkgname, "__PACKAGE__")) return PL_curstash; @@ -2921,10 +3006,10 @@ S_find_in_my_stash(pTHX_ const char *pkgname, I32 len) if (gv && GvCV(gv)) { SV * const sv = cv_const_sv(GvCV(gv)); if (sv) - pkgname = SvPV_nolen_const(sv); + pkgname = SvPV_const(sv, len); } - return gv_stashpv(pkgname, 0); + return gv_stashpvn(pkgname, len, 0); } /* @@ -2937,7 +3022,7 @@ S_readpipe_override(pTHX) { GV **gvp; GV *gv_readpipe = gv_fetchpvs("readpipe", GV_NOTQUAL, SVt_PVCV); - yylval.ival = OP_BACKTICK; + pl_yylval.ival = OP_BACKTICK; if ((gv_readpipe && GvCVu(gv_readpipe) && GvIMPORTED_CV(gv_readpipe)) || @@ -2950,9 +3035,6 @@ S_readpipe_override(pTHX) newSVOP(OP_CONST, 0, &PL_sv_undef), /* value will be read later */ newCVREF(0, newGVOP(OP_GV, 0, gv_readpipe)))); } - else { - set_csh(); - } } #ifdef PERL_MAD @@ -3063,8 +3145,8 @@ Perl_madlex(pTHX) case FUNC0SUB: case UNIOPSUB: case LSTOPSUB: - if (yylval.opval) - append_madprops(PL_thismad, yylval.opval, 0); + if (pl_yylval.opval) + append_madprops(PL_thismad, pl_yylval.opval, 0); PL_thismad = 0; return optype; @@ -3134,7 +3216,7 @@ Perl_madlex(pTHX) } /* Create new token struct. Note: opvals return early above. */ - yylval.tkval = newTOKEN(optype, yylval, PL_thismad); + pl_yylval.tkval = newTOKEN(optype, pl_yylval, PL_thismad); PL_thismad = 0; return optype; } @@ -3143,6 +3225,9 @@ Perl_madlex(pTHX) STATIC char * S_tokenize_use(pTHX_ int is_use, char *s) { dVAR; + + PERL_ARGS_ASSERT_TOKENIZE_USE; + if (PL_expect != XSTATE) yyerror(Perl_form(aTHX_ "\"%s\" not allowed in expression", is_use ? "use" : "no")); @@ -3163,7 +3248,7 @@ S_tokenize_use(pTHX_ int is_use, char *s) { s = force_word(s,WORD,FALSE,TRUE,FALSE); s = force_version(s, FALSE); } - yylval.ival = is_use; + pl_yylval.ival = is_use; return s; } #ifdef DEBUGGING @@ -3244,12 +3329,12 @@ Perl_yylex(pTHX) case LEX_KNOWNEXT: #ifdef PERL_MAD PL_lasttoke--; - yylval = PL_nexttoke[PL_lasttoke].next_val; + pl_yylval = PL_nexttoke[PL_lasttoke].next_val; if (PL_madskills) { PL_thismad = PL_nexttoke[PL_lasttoke].next_mad; PL_nexttoke[PL_lasttoke].next_mad = 0; if (PL_thismad && PL_thismad->mad_key == '_') { - PL_thiswhite = (SV*)PL_thismad->mad_val; + PL_thiswhite = MUTABLE_SV(PL_thismad->mad_val); PL_thismad->mad_val = 0; mad_free(PL_thismad); PL_thismad = 0; @@ -3264,7 +3349,7 @@ Perl_yylex(pTHX) } #else PL_nexttoke--; - yylval = PL_nextval[PL_nexttoke]; + pl_yylval = PL_nextval[PL_nexttoke]; if (!PL_nexttoke) { PL_lex_state = PL_lex_defer; PL_expect = PL_lex_expect; @@ -3365,8 +3450,10 @@ Perl_yylex(pTHX) else Perl_croak(aTHX_ "panic: yylex"); if (PL_madskills) { - SV* const tmpsv = newSVpvs(""); - Perl_sv_catpvf(aTHX_ tmpsv, "\\%c", *s); + SV* const tmpsv = newSVpvs("\\ "); + /* replace the space with the character we want to escape + */ + SvPVX(tmpsv)[1] = *s; curmad('_', tmpsv); } PL_bufptr = s + 1; @@ -3477,8 +3564,8 @@ Perl_yylex(pTHX) if (!PL_lex_inpat) sv = tokeq(sv); else if ( PL_hints & HINT_NEW_RE ) - sv = new_constant(NULL, 0, "qr", sv, sv, "q"); - yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); + sv = new_constant(NULL, 0, "qr", sv, sv, "q", 1); + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); s = PL_bufend; } else { @@ -3494,7 +3581,7 @@ Perl_yylex(pTHX) if (PL_madskills) { curmad('X', newSVpvn(PL_bufptr,s-PL_bufptr)); } - NEXTVAL_NEXTTOKE = yylval; + NEXTVAL_NEXTTOKE = pl_yylval; PL_expect = XTERM; force_next(THING); if (PL_lex_starts++) { @@ -3542,7 +3629,8 @@ Perl_yylex(pTHX) default: if (isIDFIRST_lazy_if(s,UTF)) goto keylookup; - Perl_croak(aTHX_ "Unrecognized character \\x%02X", *s & 255); + len = UTF ? Perl_utf8_length(aTHX_ (U8 *) PL_linestart, (U8 *) s) : (STRLEN) (s - PL_linestart); + Perl_croak(aTHX_ "Unrecognized character \\x%02X in column %d", *s & 255, (int) len + 1); case 4: case 26: goto fake_eof; /* emulate EOF on ^D or ^Z */ @@ -3575,19 +3663,36 @@ Perl_yylex(pTHX) if (PL_madskills) PL_faketokens = 1; #endif - sv_setpv(PL_linestr,incl_perldb()); - if (SvCUR(PL_linestr)) - sv_catpvs(PL_linestr,";"); - if (PL_preambleav){ - while(AvFILLp(PL_preambleav) >= 0) { - SV *tmpsv = av_shift(PL_preambleav); - sv_catsv(PL_linestr, tmpsv); + if (PL_perldb) { + /* Generate a string of Perl code to load the debugger. + * If PERL5DB is set, it will return the contents of that, + * otherwise a compile-time require of perl5db.pl. */ + + const char * const pdb = PerlEnv_getenv("PERL5DB"); + + if (pdb) { + sv_setpv(PL_linestr, pdb); + sv_catpvs(PL_linestr,";"); + } else { + SETERRNO(0,SS_NORMAL); + sv_setpvs(PL_linestr, "BEGIN { require 'perl5db.pl' };"); + } + } else + sv_setpvs(PL_linestr,""); + if (PL_preambleav) { + SV **svp = AvARRAY(PL_preambleav); + SV **const end = svp + AvFILLp(PL_preambleav); + while(svp <= end) { + sv_catsv(PL_linestr, *svp); + ++svp; sv_catpvs(PL_linestr, ";"); - sv_free(tmpsv); } - sv_free((SV*)PL_preambleav); + sv_free(MUTABLE_SV(PL_preambleav)); PL_preambleav = NULL; } + if (PL_minus_E) + sv_catpvs(PL_linestr, + "use feature ':5." STRINGIFY(PERL_VERSION) "';"); if (PL_minus_n || PL_minus_p) { sv_catpvs(PL_linestr, "LINE: while (<>) {"); if (PL_minus_l) @@ -3619,13 +3724,11 @@ Perl_yylex(pTHX) sv_catpvs(PL_linestr,"our @F=split(' ');"); } } - if (PL_minus_E) - sv_catpvs(PL_linestr,"use feature ':5.10';"); sv_catpvs(PL_linestr, "\n"); PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); PL_last_lop = PL_last_uni = NULL; - if (PERLDB_LINE && PL_curstash != PL_debstash) + if ((PERLDB_LINE || PERLDB_SAVESRC) && PL_curstash != PL_debstash) update_debugger_info(PL_linestr, NULL, 0); goto retry; } @@ -3637,9 +3740,7 @@ Perl_yylex(pTHX) PL_realtokenstart = -1; #endif if (PL_rsfp) { - if (PL_preprocess && !PL_in_eval) - (void)PerlProc_pclose(PL_rsfp); - else if ((PerlIO *)PL_rsfp == PerlIO_stdin()) + if ((PerlIO *)PL_rsfp == PerlIO_stdin()) PerlIO_clearerr(PL_rsfp); else (void)PerlIO_close(PL_rsfp); @@ -3651,10 +3752,10 @@ Perl_yylex(pTHX) if (PL_madskills) PL_faketokens = 1; #endif - sv_setpv(PL_linestr, - (const char *) - (PL_minus_p - ? ";}continue{print;}" : ";}")); + if (PL_minus_p) + sv_setpvs(PL_linestr, ";}continue{print;}"); + else + sv_setpvs(PL_linestr, ";}"); PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); PL_last_lop = PL_last_uni = NULL; @@ -3663,7 +3764,7 @@ Perl_yylex(pTHX) } PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr); PL_last_lop = PL_last_uni = NULL; - sv_setpvn(PL_linestr,"",0); + sv_setpvs(PL_linestr,""); TOKEN(';'); /* not infinite loop because rsfp is NULL now */ } /* If it looks like the start of a BOM or raw UTF-16, @@ -3686,16 +3787,7 @@ Perl_yylex(pTHX) # endif # endif #endif -#ifdef FTELL_FOR_PIPE_IS_BROKEN - /* This loses the possibility to detect the bof - * situation on perl -P when the libc5 is being used. - * Workaround? Maybe attach some extra state to PL_rsfp? - */ - if (!PL_preprocess) - bof = PerlIO_tell(PL_rsfp) == SvCUR(PL_linestr); -#else bof = PerlIO_tell(PL_rsfp) == (Off_t)SvCUR(PL_linestr); -#endif if (bof) { PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); s = swallow_bom((U8*)s); @@ -3708,7 +3800,7 @@ Perl_yylex(pTHX) sv_catsv(PL_thiswhite, PL_linestr); #endif if (*s == '=' && strnEQ(s, "=cut", 4) && !isALPHA(s[4])) { - sv_setpvn(PL_linestr, "", 0); + sv_setpvs(PL_linestr, ""); PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); PL_last_lop = PL_last_uni = NULL; @@ -3718,7 +3810,7 @@ Perl_yylex(pTHX) incline(s); } while (PL_doextract); PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = s; - if (PERLDB_LINE && PL_curstash != PL_debstash) + if ((PERLDB_LINE || PERLDB_SAVESRC) && PL_curstash != PL_debstash) update_debugger_info(PL_linestr, NULL, 0); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); PL_last_lop = PL_last_uni = NULL; @@ -3871,17 +3963,18 @@ Perl_yylex(pTHX) const U32 oldpdb = PL_perldb; const bool oldn = PL_minus_n; const bool oldp = PL_minus_p; + const char *d1 = d; do { - if (*d == 'M' || *d == 'm' || *d == 'C') { - const char * const m = d; - while (*d && !isSPACE(*d)) - d++; + if (*d1 == 'M' || *d1 == 'm' || *d1 == 'C') { + const char * const m = d1; + while (*d1 && !isSPACE(*d1)) + d1++; Perl_croak(aTHX_ "Too late for \"-%.*s\" option", - (int)(d - m), m); + (int)(d1 - m), m); } - d = moreswitches(d); - } while (d); + d1 = moreswitches(d1); + } while (d1); if (PL_doswitches && !switches_done) { int argc = PL_origargc; char **argv = PL_origargv; @@ -3890,17 +3983,17 @@ Perl_yylex(pTHX) } while (argc && argv[0][0] == '-' && argv[0][1]); init_argv_symbols(argc,argv); } - if ((PERLDB_LINE && !oldpdb) || + if (((PERLDB_LINE || PERLDB_SAVESRC) && !oldpdb) || ((PL_minus_n || PL_minus_p) && !(oldn || oldp))) /* if we have already added "LINE: while (<>) {", we must not do it again */ { - sv_setpvn(PL_linestr, "", 0); + sv_setpvs(PL_linestr, ""); PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); PL_last_lop = PL_last_uni = NULL; PL_preambled = FALSE; - if (PERLDB_LINE) + if (PERLDB_LINE || PERLDB_SAVESRC) (void)gv_fetchfile(PL_origfilename); goto retry; } @@ -3994,7 +4087,7 @@ Perl_yylex(pTHX) if (!PL_thiswhite) PL_thiswhite = newSVpvs(""); if (CopLINE(PL_curcop) == 1) { - sv_setpvn(PL_thiswhite, "", 0); + sv_setpvs(PL_thiswhite, ""); PL_faketokens = 0; } sv_catpvn(PL_thiswhite, s, d - s); @@ -4215,7 +4308,6 @@ Perl_yylex(pTHX) switch (tmp) { case KEY_or: case KEY_and: - case KEY_err: case KEY_for: case KEY_unless: case KEY_if: @@ -4253,7 +4345,7 @@ Perl_yylex(pTHX) sv_free(sv); if (PL_in_my == KEY_our) { #ifdef USE_ITHREADS - GvUNIQUE_on(cGVOPx_gv(yylval.opval)); + GvUNIQUE_on(cGVOPx_gv(pl_yylval.opval)); #else /* skip to avoid loading attributes.pm */ #endif @@ -4277,10 +4369,6 @@ Perl_yylex(pTHX) sv_free(sv); CvMETHOD_on(PL_compcv); } - else if (!PL_in_my && len == 9 && strnEQ(SvPVX(sv), "assertion", len)) { - sv_free(sv); - CvASSERTION_on(PL_compcv); - } /* After we've set the flags, it could be argued that we don't need to do the attributes.pm-based setting process, and shouldn't bother appending recognized @@ -4375,7 +4463,9 @@ Perl_yylex(pTHX) --PL_lex_brackets; if (PL_lex_state == LEX_INTERPNORMAL) { if (PL_lex_brackets == 0) { - if (*s != '[' && *s != '{' && (*s != '-' || s[1] != '>')) + if (*s == '-' && s[1] == '>') + PL_lex_state = LEX_INTERPENDMAYBE; + else if (*s != '[' && *s != '{') PL_lex_state = LEX_INTERPEND; } } @@ -4538,7 +4628,7 @@ Perl_yylex(pTHX) } break; } - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); if (isSPACE(*s) || *s == '#') PL_copline = NOLINE; /* invalidate current command line number */ TOKEN('{'); @@ -4561,7 +4651,7 @@ Perl_yylex(pTHX) if (PL_madskills) { if (!PL_thiswhite) PL_thiswhite = newSVpvs(""); - sv_catpvn(PL_thiswhite,"}",1); + sv_catpvs(PL_thiswhite,"}"); } #endif return yylex(); /* ignore fake brackets */ @@ -4598,7 +4688,7 @@ Perl_yylex(pTHX) && isIDFIRST_lazy_if(s,UTF)) { CopLINE_dec(PL_curcop); - Perl_warner(aTHX_ packWARN(WARN_SEMICOLON), PL_warn_nosemi); + Perl_warner(aTHX_ packWARN(WARN_SEMICOLON), "%s", PL_warn_nosemi); CopLINE_inc(PL_curcop); } BAop(OP_BIT_AND); @@ -4611,7 +4701,7 @@ Perl_yylex(pTHX) } else PREREF('&'); - yylval.ival = (OPpENTERSUB_AMPER<<8); + pl_yylval.ival = (OPpENTERSUB_AMPER<<8); TERM('&'); case '|': @@ -4683,9 +4773,13 @@ Perl_yylex(pTHX) goto leftbracket; } } - yylval.ival = 0; + pl_yylval.ival = 0; OPERATOR(ASSIGNOP); case '!': + if (PL_expect == XSTATE && s[1] == '!' && s[2] == '!') { + s += 3; + LOP(OP_DIE,XTERM); + } s++; { const char tmp = *s++; @@ -4787,9 +4881,9 @@ Perl_yylex(pTHX) /* This kludge not intended to be bulletproof. */ if (PL_tokenbuf[1] == '[' && !PL_tokenbuf[2]) { - yylval.opval = newSVOP(OP_CONST, 0, + pl_yylval.opval = newSVOP(OP_CONST, 0, newSViv(CopARYBASE_get(&PL_compiling))); - yylval.opval->op_private = OPpCONST_ARYBASE; + pl_yylval.opval->op_private = OPpCONST_ARYBASE; TERM(THING); } @@ -4937,10 +5031,14 @@ Perl_yylex(pTHX) AOPERATOR(DORDOR); } case '?': /* may either be conditional or pattern */ - if(PL_expect == XOPERATOR) { + if (PL_expect == XSTATE && s[1] == '?' && s[2] == '?') { + s += 3; + LOP(OP_WARN,XTERM); + } + if (PL_expect == XOPERATOR) { char tmp = *s++; if(tmp == '?') { - OPERATOR('?'); + OPERATOR('?'); } else { tmp = *s++; @@ -4979,16 +5077,20 @@ Perl_yylex(pTHX) PL_expect = XSTATE; goto rightbracket; } + if (PL_expect == XSTATE && s[1] == '.' && s[2] == '.') { + s += 3; + OPERATOR(YADAYADA); + } if (PL_expect == XOPERATOR || !isDIGIT(s[1])) { char tmp = *s++; if (*s == tmp) { s++; if (*s == tmp) { s++; - yylval.ival = OPf_SPECIAL; + pl_yylval.ival = OPf_SPECIAL; } else - yylval.ival = 0; + pl_yylval.ival = 0; OPERATOR(DOTDOT); } if (PL_expect != XOPERATOR) @@ -4998,7 +5100,7 @@ Perl_yylex(pTHX) /* FALL THROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - s = scan_num(s, &yylval); + s = scan_num(s, &pl_yylval); DEBUG_T( { printbuf("### Saw number in %s\n", s); } ); if (PL_expect == XOPERATOR) no_op("Number",s); @@ -5018,7 +5120,7 @@ Perl_yylex(pTHX) } if (!s) missingterm(NULL); - yylval.ival = OP_CONST; + pl_yylval.ival = OP_CONST; TERM(sublex_start()); case '"': @@ -5035,12 +5137,12 @@ Perl_yylex(pTHX) } if (!s) missingterm(NULL); - yylval.ival = OP_CONST; + pl_yylval.ival = OP_CONST; /* FIXME. I think that this can be const if char *d is replaced by more localised variables. */ for (d = SvPV(PL_lex_stuff, len); len; len--, d++) { if (*d == '$' || *d == '@' || *d == '\\' || !UTF8_IS_INVARIANT((U8)*d)) { - yylval.ival = OP_STRINGIFY; + pl_yylval.ival = OP_STRINGIFY; break; } } @@ -5071,21 +5173,16 @@ Perl_yylex(pTHX) while (isDIGIT(*start) || *start == '_') start++; if (*start == '.' && isDIGIT(start[1])) { - s = scan_num(s, &yylval); + s = scan_num(s, &pl_yylval); TERM(THING); } /* avoid v123abc() or $h{v1}, allow C */ else if (!isALPHA(*start) && (PL_expect == XTERM || PL_expect == XREF || PL_expect == XSTATE || PL_expect == XTERMORDORDOR)) { - /* XXX Use gv_fetchpvn rather than stomping on a const string */ - const char c = *start; - GV *gv; - *start = '\0'; - gv = gv_fetchpv(s, 0, SVt_PVCV); - *start = c; + GV *const gv = gv_fetchpvn_flags(s, start - s, 0, SVt_PVCV); if (!gv) { - s = scan_num(s, &yylval); + s = scan_num(s, &pl_yylval); TERM(THING); } } @@ -5154,7 +5251,7 @@ Perl_yylex(pTHX) if (!tmp && PL_expect == XSTATE && d < PL_bufend && *d == ':' && *(d + 1) != ':') { s = d + 1; - yylval.pval = CopLABEL_alloc(PL_tokenbuf); + pl_yylval.pval = CopLABEL_alloc(PL_tokenbuf); CLINE; TOKEN(LABEL); } @@ -5165,10 +5262,10 @@ Perl_yylex(pTHX) /* Is this a word before a => operator? */ if (*d == '=' && d[1] == '>') { CLINE; - yylval.opval + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, S_newSV_maybe_utf8(aTHX_ PL_tokenbuf, len)); - yylval.opval->op_private = OPpCONST_BARE; + pl_yylval.opval->op_private = OPpCONST_BARE; TERM(WORD); } @@ -5199,8 +5296,7 @@ Perl_yylex(pTHX) } else if (gv && !gvp && -tmp==KEY_lock /* XXX generalizable kludge */ - && GvCVu(gv) - && !hv_fetchs(GvHVn(PL_incgv), "Thread.pm", FALSE)) + && GvCVu(gv)) { tmp = 0; /* any sub overrides "weak" keyword */ } @@ -5260,7 +5356,7 @@ Perl_yylex(pTHX) if (PL_expect == XOPERATOR) { if (PL_bufptr == PL_linestart) { CopLINE_dec(PL_curcop); - Perl_warner(aTHX_ packWARN(WARN_SEMICOLON), PL_warn_nosemi); + Perl_warner(aTHX_ packWARN(WARN_SEMICOLON), "%s", PL_warn_nosemi); CopLINE_inc(PL_curcop); } else @@ -5311,7 +5407,7 @@ Perl_yylex(pTHX) #ifdef PERL_MAD if (PL_madskills && !PL_thistoken) { char *start = SvPVX(PL_linestr) + PL_realtokenstart; - PL_thistoken = newSVpv(start,s - start); + PL_thistoken = newSVpvn(start,s - start); PL_realtokenstart = s - SvPVX(PL_linestr); } #endif @@ -5319,8 +5415,8 @@ Perl_yylex(pTHX) /* Presume this is going to be a bareword of some sort. */ CLINE; - yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); - yylval.opval->op_private = OPpCONST_BARE; + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); + pl_yylval.opval->op_private = OPpCONST_BARE; /* UTF-8 package name? */ if (UTF && !IN_BYTES && is_utf8_string((U8*)SvPVX_const(sv), SvCUR(sv))) @@ -5342,7 +5438,7 @@ Perl_yylex(pTHX) /* Real typeglob, so get the real subroutine: */ ? GvCVu(gv) /* A proxy for a subroutine in this package? */ - : SvOK(gv) ? (CV *) gv : NULL) + : SvOK(gv) ? MUTABLE_CV(gv) : NULL) : NULL; /* See if it's the indirect object for a list operator. */ @@ -5399,9 +5495,9 @@ Perl_yylex(pTHX) /* Is this a word before a => operator? */ if (*s == '=' && s[1] == '>' && !pkgname) { CLINE; - sv_setpv(((SVOP*)yylval.opval)->op_sv, PL_tokenbuf); + sv_setpv(((SVOP*)pl_yylval.opval)->op_sv, PL_tokenbuf); if (UTF && !IN_BYTES && is_utf8_string((U8*)PL_tokenbuf, len)) - SvUTF8_on(((SVOP*)yylval.opval)->op_sv); + SvUTF8_on(((SVOP*)pl_yylval.opval)->op_sv); TERM(WORD); } @@ -5414,18 +5510,7 @@ Perl_yylex(pTHX) d++; if (*d == ')' && (sv = gv_const_sv(gv))) { s = d + 1; -#ifdef PERL_MAD - if (PL_madskills) { - char *par = SvPVX(PL_linestr) + PL_realtokenstart; - sv_catpvn(PL_thistoken, par, s - par); - if (PL_nextwhite) { - sv_free(PL_nextwhite); - PL_nextwhite = 0; - } - } - else -#endif - goto its_constant; + goto its_constant; } } #ifdef PERL_MAD @@ -5435,7 +5520,7 @@ Perl_yylex(pTHX) } start_force(PL_curforce); #endif - NEXTVAL_NEXTTOKE.opval = yylval.opval; + NEXTVAL_NEXTTOKE.opval = pl_yylval.opval; PL_expect = XOPERATOR; #ifdef PERL_MAD if (PL_madskills) { @@ -5445,7 +5530,7 @@ Perl_yylex(pTHX) } #endif force_next(WORD); - yylval.ival = 0; + pl_yylval.ival = 0; TOKEN('&'); } @@ -5472,11 +5557,11 @@ Perl_yylex(pTHX) "Ambiguous use of -%s resolved as -&%s()", PL_tokenbuf, PL_tokenbuf); /* Check for a constant sub */ - if ((sv = gv_const_sv(gv)) && !PL_madskills) { + if ((sv = gv_const_sv(gv))) { its_constant: - SvREFCNT_dec(((SVOP*)yylval.opval)->op_sv); - ((SVOP*)yylval.opval)->op_sv = SvREFCNT_inc_simple(sv); - yylval.opval->op_private = 0; + SvREFCNT_dec(((SVOP*)pl_yylval.opval)->op_sv); + ((SVOP*)pl_yylval.opval)->op_sv = SvREFCNT_inc_simple(sv); + pl_yylval.opval->op_private = 0; TOKEN(WORD); } @@ -5489,9 +5574,9 @@ Perl_yylex(pTHX) cv = GvCV(gv); } - op_free(yylval.opval); - yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv)); - yylval.opval->op_private |= OPpENTERSUB_NOPAREN; + op_free(pl_yylval.opval); + pl_yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv)); + pl_yylval.opval->op_private |= OPpENTERSUB_NOPAREN; PL_last_lop = PL_oldbufptr; PL_last_lop_op = OP_ENTERSUB; /* Is there a prototype? */ @@ -5502,7 +5587,7 @@ Perl_yylex(pTHX) SvPOK(cv)) { STRLEN protolen; - const char *proto = SvPV_const((SV*)cv, protolen); + const char *proto = SvPV_const(MUTABLE_SV(cv), protolen); if (!protolen) TERM(FUNC0SUB); if ((*proto == '$' || *proto == '_') && proto[1] == '\0') @@ -5510,10 +5595,10 @@ Perl_yylex(pTHX) while (*proto == ';') proto++; if (*proto == '&' && *s == '{') { - sv_setpv(PL_subname, - (const char *) - (PL_curstash ? - "__ANON__" : "__ANON__::__ANON__")); + if (PL_curstash) + sv_setpvs(PL_subname, "__ANON__"); + else + sv_setpvs(PL_subname, "__ANON__::__ANON__"); PREBLOCK(LSTOPSUB); } } @@ -5524,7 +5609,7 @@ Perl_yylex(pTHX) PL_thiswhite = 0; } start_force(PL_curforce); - NEXTVAL_NEXTTOKE.opval = yylval.opval; + NEXTVAL_NEXTTOKE.opval = pl_yylval.opval; PL_expect = XTERM; if (PL_madskills) { PL_nextwhite = nextPL_nextwhite; @@ -5557,15 +5642,15 @@ Perl_yylex(pTHX) } if (probable_sub) { gv = gv_fetchpv(PL_tokenbuf, GV_ADD, SVt_PVCV); - op_free(yylval.opval); - yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv)); - yylval.opval->op_private |= OPpENTERSUB_NOPAREN; + op_free(pl_yylval.opval); + pl_yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv)); + pl_yylval.opval->op_private |= OPpENTERSUB_NOPAREN; PL_last_lop = PL_oldbufptr; PL_last_lop_op = OP_ENTERSUB; PL_nextwhite = PL_thiswhite; PL_thiswhite = 0; start_force(PL_curforce); - NEXTVAL_NEXTTOKE.opval = yylval.opval; + NEXTVAL_NEXTTOKE.opval = pl_yylval.opval; PL_expect = XTERM; PL_nextwhite = nextPL_nextwhite; curmad('X', PL_thistoken); @@ -5574,7 +5659,7 @@ Perl_yylex(pTHX) TOKEN(NOAMP); } #else - NEXTVAL_NEXTTOKE.opval = yylval.opval; + NEXTVAL_NEXTTOKE.opval = pl_yylval.opval; PL_expect = XTERM; force_next(WORD); TOKEN(NOAMP); @@ -5583,10 +5668,10 @@ Perl_yylex(pTHX) /* Call it a bare word */ + bareword: if (PL_hints & HINT_STRICT_SUBS) - yylval.opval->op_private |= OPpCONST_STRICT; + pl_yylval.opval->op_private |= OPpCONST_STRICT; else { - bareword: if (lastchar != '-') { if (ckWARN(WARN_RESERVED)) { d = PL_tokenbuf; @@ -5613,17 +5698,17 @@ Perl_yylex(pTHX) } case KEY___FILE__: - yylval.opval = (OP*)newSVOP(OP_CONST, 0, + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(CopFILE(PL_curcop),0)); TERM(THING); case KEY___LINE__: - yylval.opval = (OP*)newSVOP(OP_CONST, 0, + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, Perl_newSVpvf(aTHX_ "%"IVdf, (IV)CopLINE(PL_curcop))); TERM(THING); case KEY___PACKAGE__: - yylval.opval = (OP*)newSVOP(OP_CONST, 0, + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, (PL_curstash ? newSVhek(HvNAME_HEK(PL_curstash)) : &PL_sv_undef)); @@ -5650,9 +5735,7 @@ Perl_yylex(pTHX) #endif /* Mark this internal pseudo-handle as clean */ IoFLAGS(GvIOp(gv)) |= IOf_UNTAINT; - if (PL_preprocess) - IoTYPE(GvIOp(gv)) = IoTYPE_PIPE; - else if ((PerlIO*)PL_rsfp == PerlIO_stdin()) + if ((PerlIO*)PL_rsfp == PerlIO_stdin()) IoTYPE(GvIOp(gv)) = IoTYPE_STD; else IoTYPE(GvIOp(gv)) = IoTYPE_RDONLY; @@ -5721,7 +5804,7 @@ Perl_yylex(pTHX) PL_realtokenstart = -1; } while ((s = filter_gets(PL_endwhite, PL_rsfp, - SvCUR(PL_endwhite))) != Nullch) ; + SvCUR(PL_endwhite))) != NULL) ; } #endif PL_rsfp = NULL; @@ -5863,10 +5946,10 @@ Perl_yylex(pTHX) s = force_word(s,WORD,TRUE,TRUE,FALSE); if (orig_keyword == KEY_do) { orig_keyword = 0; - yylval.ival = 1; + pl_yylval.ival = 1; } else - yylval.ival = 0; + pl_yylval.ival = 0; OPERATOR(DO); case KEY_die: @@ -5894,7 +5977,7 @@ Perl_yylex(pTHX) PREBLOCK(ELSE); case KEY_elsif: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(ELSIF); case KEY_eq: @@ -5916,9 +5999,6 @@ Perl_yylex(pTHX) case KEY_eof: UNI(OP_EOF); - case KEY_err: - OPERATOR(DOROP); - case KEY_exp: UNI(OP_EXP); @@ -5926,7 +6006,6 @@ Perl_yylex(pTHX) UNI(OP_EACH); case KEY_exec: - set_csh(); LOP(OP_EXEC,XREF); case KEY_endhostent: @@ -5949,7 +6028,7 @@ Perl_yylex(pTHX) case KEY_for: case KEY_foreach: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); s = SKIPSPACE1(s); if (PL_expect == XSTATE && isIDFIRST_lazy_if(s,UTF)) { char *p = s; @@ -6087,18 +6166,17 @@ Perl_yylex(pTHX) FUN0(OP_GETLOGIN); case KEY_given: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(GIVEN); case KEY_glob: - set_csh(); LOP(OP_GLOB,XTERM); case KEY_hex: UNI(OP_HEX); case KEY_if: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(IF); case KEY_index: @@ -6130,7 +6208,7 @@ Perl_yylex(pTHX) UNI(OP_LCFIRST); case KEY_local: - yylval.ival = 0; + pl_yylval.ival = 0; OPERATOR(LOCAL); case KEY_length: @@ -6185,7 +6263,7 @@ Perl_yylex(pTHX) case KEY_our: case KEY_my: case KEY_state: - PL_in_my = tmp; + PL_in_my = (U16)tmp; s = SKIPSPACE1(s); if (isIDFIRST_lazy_if(s,UTF)) { #ifdef PERL_MAD @@ -6209,7 +6287,7 @@ Perl_yylex(pTHX) } #endif } - yylval.ival = 1; + pl_yylval.ival = 1; OPERATOR(MY); case KEY_next: @@ -6250,7 +6328,7 @@ Perl_yylex(pTHX) LOP(OP_OPEN,XTERM); case KEY_or: - yylval.ival = OP_OR; + pl_yylval.ival = OP_OR; OPERATOR(OROP); case KEY_ord: @@ -6296,7 +6374,7 @@ Perl_yylex(pTHX) s = scan_str(s,!!PL_madskills,FALSE); if (!s) missingterm(NULL); - yylval.ival = OP_CONST; + pl_yylval.ival = OP_CONST; TERM(sublex_start()); case KEY_quotemeta: @@ -6336,9 +6414,7 @@ Perl_yylex(pTHX) for (; !isSPACE(*d) && len; --len, ++d) /**/; } - sv = newSVpvn(b, d-b); - if (DO_UTF8(PL_lex_stuff)) - SvUTF8_on(sv); + sv = newSVpvn_utf8(b, d-b, DO_UTF8(PL_lex_stuff)); words = append_elem(OP_LIST, words, newSVOP(OP_CONST, 0, tokeq(sv))); } @@ -6360,7 +6436,7 @@ Perl_yylex(pTHX) s = scan_str(s,!!PL_madskills,FALSE); if (!s) missingterm(NULL); - yylval.ival = OP_STRINGIFY; + pl_yylval.ival = OP_STRINGIFY; if (SvIVX(PL_lex_stuff) == '\'') SvIV_set(PL_lex_stuff, 0); /* qq'$foo' should intepolate */ TERM(sublex_start()); @@ -6396,10 +6472,10 @@ Perl_yylex(pTHX) } if (orig_keyword == KEY_require) { orig_keyword = 0; - yylval.ival = 1; + pl_yylval.ival = 1; } else - yylval.ival = 0; + pl_yylval.ival = 0; PL_expect = XTERM; PL_bufptr = s; PL_last_uni = PL_oldbufptr; @@ -6433,11 +6509,9 @@ Perl_yylex(pTHX) UNI(OP_READDIR); case KEY_readline: - set_csh(); UNIDOR(OP_READLINE); case KEY_readpipe: - set_csh(); UNIDOR(OP_BACKTICK); case KEY_rewinddir: @@ -6457,7 +6531,7 @@ Perl_yylex(pTHX) case KEY_s: s = scan_subst(s); - if (yylval.opval) + if (pl_yylval.opval) TERM(sublex_start()); else TOKEN(1); /* force error */ @@ -6610,7 +6684,7 @@ Perl_yylex(pTHX) (*s == ':' && s[1] == ':')) { #ifdef PERL_MAD - SV *nametoke; + SV *nametoke = NULL; #endif PL_expect = XBLOCK; @@ -6649,7 +6723,7 @@ Perl_yylex(pTHX) Perl_croak(aTHX_ "Missing name in \"my sub\""); PL_expect = XTERMBLOCK; attrful = XATTRTERM; - sv_setpvn(PL_subname,"?",1); + sv_setpvs(PL_subname,"?"); have_name = FALSE; } @@ -6671,6 +6745,12 @@ Perl_yylex(pTHX) if (*s == '(') { char *p; bool bad_proto = FALSE; + bool in_brackets = FALSE; + char greedy_proto = ' '; + bool proto_after_greedy_proto = FALSE; + bool must_be_last = FALSE; + bool underscore = FALSE; + bool seen_underscore = FALSE; const bool warnsyntax = ckWARN(WARN_SYNTAX); s = scan_str(s,!!PL_madskills,FALSE); @@ -6682,14 +6762,47 @@ Perl_yylex(pTHX) for (p = d; *p; ++p) { if (!isSPACE(*p)) { d[tmp++] = *p; - if (warnsyntax && !strchr("$@%*;[]&\\_", *p)) - bad_proto = TRUE; + + if (warnsyntax) { + if (must_be_last) + proto_after_greedy_proto = TRUE; + if (!strchr("$@%*;[]&\\_", *p)) { + bad_proto = TRUE; + } + else { + if ( underscore ) { + if ( *p != ';' ) + bad_proto = TRUE; + underscore = FALSE; + } + if ( *p == '[' ) { + in_brackets = TRUE; + } + else if ( *p == ']' ) { + in_brackets = FALSE; + } + else if ( (*p == '@' || *p == '%') && + ( tmp < 2 || d[tmp-2] != '\\' ) && + !in_brackets ) { + must_be_last = TRUE; + greedy_proto = *p; + } + else if ( *p == '_' ) { + underscore = seen_underscore = TRUE; + } + } + } } } d[tmp] = '\0'; + if (proto_after_greedy_proto) + Perl_warner(aTHX_ packWARN(WARN_SYNTAX), + "Prototype after '%c' for %"SVf" : %s", + greedy_proto, SVfARG(PL_subname), d); if (bad_proto) Perl_warner(aTHX_ packWARN(WARN_SYNTAX), - "Illegal character in prototype for %"SVf" : %s", + "Illegal character %sin prototype for %"SVf" : %s", + seen_underscore ? "after '_' " : "", SVfARG(PL_subname), d); SvCUR_set(PL_lex_stuff, tmp); have_proto = TRUE; @@ -6702,7 +6815,7 @@ Perl_yylex(pTHX) CURMAD('Q', PL_thisclose); NEXTVAL_NEXTTOKE.opval = (OP*)newSVOP(OP_CONST, 0, PL_lex_stuff); - PL_lex_stuff = Nullsv; + PL_lex_stuff = NULL; force_next(THING); s = SKIPSPACE2(s,tmpwhite); @@ -6741,9 +6854,10 @@ Perl_yylex(pTHX) } #endif if (!have_name) { - sv_setpv(PL_subname, - (const char *) - (PL_curstash ? "__ANON__" : "__ANON__::__ANON__")); + if (PL_curstash) + sv_setpvs(PL_subname, "__ANON__"); + else + sv_setpvs(PL_subname, "__ANON__::__ANON__"); TOKEN(ANONSUB); } #ifndef PERL_MAD @@ -6756,7 +6870,6 @@ Perl_yylex(pTHX) } case KEY_system: - set_csh(); LOP(OP_SYSTEM,XREF); case KEY_symlink: @@ -6812,11 +6925,11 @@ Perl_yylex(pTHX) UNI(OP_UNTIE); case KEY_until: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(UNTIL); case KEY_unless: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(UNLESS); case KEY_unlink: @@ -6848,11 +6961,11 @@ Perl_yylex(pTHX) LOP(OP_VEC,XTERM); case KEY_when: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(WHEN); case KEY_while: - yylval.ival = CopLINE(PL_curcop); + pl_yylval.ival = CopLINE(PL_curcop); OPERATOR(WHILE); case KEY_warn: @@ -6889,7 +7002,7 @@ Perl_yylex(pTHX) goto just_a_word; case KEY_xor: - yylval.ival = OP_XOR; + pl_yylval.ival = OP_XOR; OPERATOR(OROP); case KEY_y: @@ -6910,6 +7023,9 @@ S_pending_ident(pTHX) PADOFFSET tmp = 0; /* pit holds the identifier we read and pending_ident is reset */ char pit = PL_pending_ident; + const STRLEN tokenbuf_len = strlen(PL_tokenbuf); + /* All routes through this function want to know if there is a colon. */ + const char *const has_colon = (const char*) memchr (PL_tokenbuf, ':', tokenbuf_len); PL_pending_ident = 0; /* PL_realtokenstart = realtokenend = PL_bufptr - SvPVX(PL_linestr); */ @@ -6924,19 +7040,19 @@ S_pending_ident(pTHX) */ if (PL_in_my) { if (PL_in_my == KEY_our) { /* "our" is merely analogous to "my" */ - if (strchr(PL_tokenbuf,':')) + if (has_colon) yyerror(Perl_form(aTHX_ "No package name allowed for " "variable %s in \"our\"", PL_tokenbuf)); tmp = allocmy(PL_tokenbuf); } else { - if (strchr(PL_tokenbuf,':')) + if (has_colon) yyerror(Perl_form(aTHX_ PL_no_myglob, PL_in_my == KEY_my ? "my" : "state", PL_tokenbuf)); - yylval.opval = newOP(OP_PADANY, 0); - yylval.opval->op_targ = allocmy(PL_tokenbuf); + pl_yylval.opval = newOP(OP_PADANY, 0); + pl_yylval.opval->op_targ = allocmy(PL_tokenbuf); return PRIVATEREF; } } @@ -6953,7 +7069,7 @@ S_pending_ident(pTHX) (although why you'd do that is anyone's guess). */ - if (!strchr(PL_tokenbuf,':')) { + if (!has_colon) { if (!PL_in_my) tmp = pad_findmy(PL_tokenbuf); if (tmp != NOT_IN_PAD) { @@ -6964,9 +7080,9 @@ S_pending_ident(pTHX) HEK * const stashname = HvNAME_HEK(stash); SV * const sym = newSVhek(stashname); sv_catpvs(sym, "::"); - sv_catpv(sym, PL_tokenbuf+1); - yylval.opval = (OP*)newSVOP(OP_CONST, 0, sym); - yylval.opval->op_private = OPpCONST_ENTERED; + sv_catpvn(sym, PL_tokenbuf+1, tokenbuf_len - 1); + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sym); + pl_yylval.opval->op_private = OPpCONST_ENTERED; gv_fetchsv(sym, (PL_in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) @@ -6995,8 +7111,8 @@ S_pending_ident(pTHX) } } - yylval.opval = newOP(OP_PADANY, 0); - yylval.opval->op_targ = tmp; + pl_yylval.opval = newOP(OP_PADANY, 0); + pl_yylval.opval->op_targ = tmp; return PRIVATEREF; } } @@ -7007,7 +7123,8 @@ S_pending_ident(pTHX) table. */ if (pit == '@' && PL_lex_state != LEX_NORMAL && !PL_lex_brackets) { - GV *gv = gv_fetchpv(PL_tokenbuf+1, 0, SVt_PVAV); + GV *const gv = gv_fetchpvn_flags(PL_tokenbuf + 1, tokenbuf_len - 1, 0, + SVt_PVAV); if ((!gv || ((PL_tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv))) && ckWARN(WARN_AMBIGUOUS) /* DO NOT warn for @- and @+ */ @@ -7023,10 +7140,11 @@ S_pending_ident(pTHX) } /* build ops for a bareword */ - yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf+1, 0)); - yylval.opval->op_private = OPpCONST_ENTERED; - gv_fetchpv( - PL_tokenbuf+1, + pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpvn(PL_tokenbuf + 1, + tokenbuf_len - 1)); + pl_yylval.opval->op_private = OPpCONST_ENTERED; + gv_fetchpvn_flags( + PL_tokenbuf + 1, tokenbuf_len - 1, /* If the identifier refers to a stash, don't autovivify it. * Change 24660 had the side effect of causing symbol table * hashes to always be defined, even if they were freshly @@ -7039,7 +7157,9 @@ S_pending_ident(pTHX) * tests still give the expected answers, even though what * they're actually testing has now changed subtly. */ - (*PL_tokenbuf == '%' && *(d = PL_tokenbuf + strlen(PL_tokenbuf) - 1) == ':' && d[-1] == ':' + (*PL_tokenbuf == '%' + && *(d = PL_tokenbuf + tokenbuf_len - 1) == ':' + && d[-1] == ':' ? 0 : PL_in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : GV_ADD), ((PL_tokenbuf[0] == '$') ? SVt_PV @@ -7056,6 +7176,9 @@ I32 Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) { dVAR; + + PERL_ARGS_ASSERT_KEYWORD; + switch (len) { case 1: /* 5 tokens of length 1 */ @@ -7322,14 +7445,6 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords) goto unknown; - case 'r': - if (name[2] == 'r') - { /* err */ - return (all_keywords || FEATURE_IS_ENABLED("err") ? -KEY_err : 0); - } - - goto unknown; - case 'x': if (name[2] == 'p') { /* exp */ @@ -10452,6 +10567,8 @@ S_checkcomma(pTHX_ const char *s, const char *name, const char *what) { dVAR; + PERL_ARGS_ASSERT_CHECKCOMMA; + if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way */ if (ckWARN(WARN_SYNTAX)) { int level = 1; @@ -10504,8 +10621,8 @@ S_checkcomma(pTHX_ const char *s, const char *name, const char *what) and type is used with error messages only. */ STATIC SV * -S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv, - const char *type) +S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, STRLEN keylen, + SV *sv, SV *pv, const char *type, STRLEN typelen) { dVAR; dSP; HV * const table = GvHV(PL_hintgv); /* ^H */ @@ -10514,6 +10631,8 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv, SV *cv, *typesv; const char *why1 = "", *why2 = "", *why3 = ""; + PERL_ARGS_ASSERT_NEW_CONSTANT; + if (!table || !(PL_hints & HINT_LOCALIZE_HH)) { SV *msg; @@ -10539,7 +10658,7 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv, SvREFCNT_dec(msg); return sv; } - cvp = hv_fetch(table, key, strlen(key), FALSE); + cvp = hv_fetch(table, key, keylen, FALSE); if (!cvp || !SvOK(*cvp)) { why1 = "$^H{"; why2 = key; @@ -10549,9 +10668,9 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv, sv_2mortal(sv); /* Parent created it permanently */ cv = *cvp; if (!pv && s) - pv = sv_2mortal(newSVpvn(s, len)); + pv = newSVpvn_flags(s, len, SVs_TEMP); if (type && pv) - typesv = sv_2mortal(newSVpv(type, 0)); + typesv = newSVpvn_flags(type, typelen, SVs_TEMP); else typesv = &PL_sv_undef; @@ -10608,6 +10727,9 @@ S_scan_word(pTHX_ register char *s, char *dest, STRLEN destlen, int allow_packag dVAR; register char *d = dest; register char * const e = d + destlen - 3; /* two-character token, ending NUL */ + + PERL_ARGS_ASSERT_SCAN_WORD; + for (;;) { if (d >= e) Perl_croak(aTHX_ ident_too_long); @@ -10651,6 +10773,8 @@ S_scan_ident(pTHX_ register char *s, register const char *send, char *dest, STRL register char *d = dest; register char * const e = d + destlen + 3; /* two-character token, ending NUL */ + PERL_ARGS_ASSERT_SCAN_IDENT; + if (isSPACE(*s)) s = PEEKSPACE(s); if (isDIGIT(*s)) { @@ -10805,9 +10929,11 @@ S_scan_ident(pTHX_ register char *s, register const char *send, char *dest, STRL void Perl_pmflag(pTHX_ U32* pmfl, int ch) { + PERL_ARGS_ASSERT_PMFLAG; + PERL_UNUSED_CONTEXT; if (ch<256) { - char c = (char)ch; + const char c = (char)ch; switch (c) { CASE_STD_PMMOD_FLAGS_PARSE_SET(pmfl); case GLOBAL_PAT_MOD: *pmfl |= PMf_GLOBAL; break; @@ -10830,6 +10956,7 @@ S_scan_pat(pTHX_ char *start, I32 type) char *modstart; #endif + PERL_ARGS_ASSERT_SCAN_PAT; if (!s) { const char * const delimiter = skipspace(start); @@ -10850,10 +10977,10 @@ S_scan_pat(pTHX_ char *start, I32 type) matches. */ assert(type != OP_TRANS); if (PL_curstash) { - MAGIC *mg = mg_find((SV*)PL_curstash, PERL_MAGIC_symtab); + MAGIC *mg = mg_find((const SV *)PL_curstash, PERL_MAGIC_symtab); U32 elements; if (!mg) { - mg = sv_magicext((SV*)PL_curstash, 0, PERL_MAGIC_symtab, 0, 0, + mg = sv_magicext(MUTABLE_SV(PL_curstash), 0, PERL_MAGIC_symtab, 0, 0, 0); } elements = mg->mg_len / sizeof(PMOP**); @@ -10883,7 +11010,7 @@ S_scan_pat(pTHX_ char *start, I32 type) } PL_lex_op = (OP*)pm; - yylval.ival = OP_MATCH; + pl_yylval.ival = OP_MATCH; return s; } @@ -10899,7 +11026,9 @@ S_scan_subst(pTHX_ char *start) char *modstart; #endif - yylval.ival = OP_NULL; + PERL_ARGS_ASSERT_SCAN_SUBST; + + pl_yylval.ival = OP_NULL; s = scan_str(start,!!PL_madskills,FALSE); @@ -10970,8 +11099,12 @@ S_scan_subst(pTHX_ char *start) PL_sublex_info.super_bufend = PL_bufend; PL_multi_end = 0; pm->op_pmflags |= PMf_EVAL; - while (es-- > 0) - sv_catpv(repl, (const char *)(es ? "eval " : "do ")); + while (es-- > 0) { + if (es) + sv_catpvs(repl, "eval "); + else + sv_catpvs(repl, "do "); + } sv_catpvs(repl, "{"); sv_catsv(repl, PL_lex_repl); if (strchr(SvPVX(PL_lex_repl), '#')) @@ -10983,7 +11116,7 @@ S_scan_subst(pTHX_ char *start) } PL_lex_op = (OP*)pm; - yylval.ival = OP_SUBST; + pl_yylval.ival = OP_SUBST; return s; } @@ -10994,14 +11127,16 @@ S_scan_trans(pTHX_ char *start) register char* s; OP *o; short *tbl; - I32 squash; - I32 del; - I32 complement; + U8 squash; + U8 del; + U8 complement; #ifdef PERL_MAD char *modstart; #endif - yylval.ival = OP_NULL; + PERL_ARGS_ASSERT_SCAN_TRANS; + + pl_yylval.ival = OP_NULL; s = scan_str(start,!!PL_madskills,FALSE); if (!s) @@ -11063,7 +11198,7 @@ S_scan_trans(pTHX_ char *start) (DO_UTF8(PL_lex_repl) ? OPpTRANS_TO_UTF : 0); PL_lex_op = o; - yylval.ival = OP_TRANS; + pl_yylval.ival = OP_TRANS; #ifdef PERL_MAD if (PL_madskills) { @@ -11098,6 +11233,8 @@ S_scan_heredoc(pTHX_ register char *s) PL_realtokenstart = -1; #endif + PERL_ARGS_ASSERT_SCAN_HEREDOC; + s += 2; d = PL_tokenbuf; e = PL_tokenbuf + sizeof PL_tokenbuf - 1; @@ -11269,7 +11406,7 @@ S_scan_heredoc(pTHX_ register char *s) PL_last_lop = PL_last_uni = NULL; } else - sv_setpvn(tmpstr,"",0); /* avoid "uninitialized" warning */ + sv_setpvs(tmpstr,""); /* avoid "uninitialized" warning */ while (s >= PL_bufend) { /* multiple line string? */ #ifdef PERL_MAD if (PL_madskills) { @@ -11306,7 +11443,7 @@ S_scan_heredoc(pTHX_ register char *s) else if (PL_bufend - PL_linestart == 1 && PL_bufend[-1] == '\r') PL_bufend[-1] = '\n'; #endif - if (PERLDB_LINE && PL_curstash != PL_debstash) + if ((PERLDB_LINE || PERLDB_SAVESRC) && PL_curstash != PL_debstash) update_debugger_info(PL_linestr, NULL, 0); if (*s == term && memEQ(s,PL_tokenbuf,len)) { STRLEN off = PL_bufend - 1 - SvPVX_const(PL_linestr); @@ -11334,14 +11471,14 @@ retval: sv_recode_to_utf8(tmpstr, PL_encoding); } PL_lex_stuff = tmpstr; - yylval.ival = op_type; + pl_yylval.ival = op_type; return s; } /* scan_inputsymbol takes: current position in input buffer returns: new position in input buffer - side-effects: yylval and lex_op are set. + side-effects: pl_yylval and lex_op are set. This code handles: @@ -11361,10 +11498,11 @@ S_scan_inputsymbol(pTHX_ char *start) register char *s = start; /* current position in buffer */ char *end; I32 len; - char *d = PL_tokenbuf; /* start of temp holding space */ const char * const e = PL_tokenbuf + sizeof PL_tokenbuf; /* end of temp holding space */ + PERL_ARGS_ASSERT_SCAN_INPUTSYMBOL; + end = strchr(s, '\n'); if (!end) end = PL_bufend; @@ -11401,8 +11539,7 @@ S_scan_inputsymbol(pTHX_ char *start) */ if (d - PL_tokenbuf != len) { - yylval.ival = OP_GLOB; - set_csh(); + pl_yylval.ival = OP_GLOB; s = scan_str(start,!!PL_madskills,FALSE); if (!s) Perl_croak(aTHX_ "Glob not terminated"); @@ -11477,8 +11614,8 @@ intro_sym: } if (!readline_overriden) PL_lex_op->op_flags |= OPf_SPECIAL; - /* we created the ops in PL_lex_op, so make yylval.ival a null op */ - yylval.ival = OP_NULL; + /* we created the ops in PL_lex_op, so make pl_yylval.ival a null op */ + pl_yylval.ival = OP_NULL; } /* If it's none of the above, it must be a literal filehandle @@ -11491,7 +11628,7 @@ intro_sym: newGVOP(OP_GV, 0, gv), newCVREF(0, newGVOP(OP_GV, 0, gv_readline)))) : (OP*)newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, gv)); - yylval.ival = OP_NULL; + pl_yylval.ival = OP_NULL; } } @@ -11562,6 +11699,8 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) char *tstart; #endif + PERL_ARGS_ASSERT_SCAN_STR; + /* skip space before the delimiter */ if (isSPACE(*s)) { s = PEEKSPACE(s); @@ -11803,7 +11942,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) CopLINE_inc(PL_curcop); /* update debugger info */ - if (PERLDB_LINE && PL_curstash != PL_debstash) + if ((PERLDB_LINE || PERLDB_SAVESRC) && PL_curstash != PL_debstash) update_debugger_info(PL_linestr, NULL, 0); /* having changed the buffer, we must update PL_bufend */ @@ -11871,7 +12010,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) scan_num takes: pointer to position in buffer returns: pointer to new position in buffer - side-effects: builds ops for the constant in yylval.op + side-effects: builds ops for the constant in pl_yylval.op Read a number in any of the formats that Perl accepts: @@ -11902,6 +12041,8 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp) const char *lastub = NULL; /* position of last underbar */ static char const number_too_long[] = "Number too long"; + PERL_ARGS_ASSERT_SCAN_NUM; + /* We use the first character to decide what type of number this is */ switch (*s) { @@ -12081,9 +12222,9 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp) } if (just_zero && (PL_hints & HINT_NEW_INTEGER)) sv = new_constant(start, s - start, "integer", - sv, NULL, NULL); + sv, NULL, NULL, 0); else if (PL_hints & HINT_NEW_BINARY) - sv = new_constant(start, s - start, "binary", sv, NULL, NULL); + sv = new_constant(start, s - start, "binary", sv, NULL, NULL, 0); } break; @@ -12246,13 +12387,13 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp) sv_setnv(sv, nv); } - if ( floatit ? (PL_hints & HINT_NEW_FLOAT) : - (PL_hints & HINT_NEW_INTEGER) ) - sv = new_constant(PL_tokenbuf, - d - PL_tokenbuf, - (const char *) - (floatit ? "float" : "integer"), - sv, NULL, NULL); + if ( floatit + ? (PL_hints & HINT_NEW_FLOAT) : (PL_hints & HINT_NEW_INTEGER) ) { + const char *const key = floatit ? "float" : "integer"; + const STRLEN keylen = floatit ? 5 : 7; + sv = S_new_constant(aTHX_ PL_tokenbuf, d - PL_tokenbuf, + key, keylen, sv, NULL, NULL, 0); + } break; /* if it starts with a v, it could be a v-string */ @@ -12284,14 +12425,16 @@ S_scan_formline(pTHX_ register char *s) bool eofmt = FALSE; #ifdef PERL_MAD char *tokenstart = s; - SV* savewhite; - + SV* savewhite = NULL; + if (PL_madskills) { savewhite = PL_thiswhite; PL_thiswhite = 0; } #endif + PERL_ARGS_ASSERT_SCAN_FORMLINE; + while (!needargs) { if (*s == '.') { t = s+1; @@ -12404,20 +12547,6 @@ S_scan_formline(pTHX_ register char *s) return s; } -STATIC void -S_set_csh(pTHX) -{ -#ifdef CSH - dVAR; - if (!PL_cshlen) - PL_cshlen = strlen(PL_cshname); -#else -#if defined(USE_ITHREADS) - PERL_UNUSED_CONTEXT; -#endif -#endif -} - I32 Perl_start_subparse(pTHX_ I32 is_format, U32 flags) { @@ -12432,12 +12561,12 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags) save_item(PL_subname); SAVESPTR(PL_compcv); - PL_compcv = (CV*)newSV_type(is_format ? SVt_PVFM : SVt_PVCV); + PL_compcv = MUTABLE_CV(newSV_type(is_format ? SVt_PVFM : SVt_PVCV)); CvFLAGS(PL_compcv) |= flags; PL_subline = CopLINE(PL_curcop); CvPADLIST(PL_compcv) = pad_new(padnew_SAVE|padnew_SAVESUB); - CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc_simple(outsidecv); + CvOUTSIDE(PL_compcv) = MUTABLE_CV(SvREFCNT_inc_simple(outsidecv)); CvOUTSIDE_SEQ(PL_compcv) = PL_cop_seqmax; return oldsavestack_ix; @@ -12447,9 +12576,12 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags) #pragma segment Perl_yylex #endif int -Perl_yywarn(pTHX_ const char *s) +Perl_yywarn(pTHX_ const char *const s) { dVAR; + + PERL_ARGS_ASSERT_YYWARN; + PL_in_eval |= EVAL_WARNONLY; yyerror(s); PL_in_eval &= ~EVAL_WARNONLY; @@ -12457,7 +12589,7 @@ Perl_yywarn(pTHX_ const char *s) } int -Perl_yyerror(pTHX_ const char *s) +Perl_yyerror(pTHX_ const char *const s) { dVAR; const char *where = NULL; @@ -12466,6 +12598,8 @@ Perl_yyerror(pTHX_ const char *s) SV *msg; int yychar = PL_parser->yychar; + PERL_ARGS_ASSERT_YYERROR; + if (!yychar || (yychar == ';' && !PL_rsfp)) where = "at EOF"; else if (PL_oldoldbufptr && PL_bufptr > PL_oldoldbufptr && @@ -12513,11 +12647,13 @@ Perl_yyerror(pTHX_ const char *s) where = "within string"; } else { - SV * const where_sv = sv_2mortal(newSVpvs("next char ")); + SV * const where_sv = newSVpvs_flags("next char ", SVs_TEMP); if (yychar < 32) Perl_sv_catpvf(aTHX_ where_sv, "^%c", toCTRL(yychar)); - else if (isPRINT_LC(yychar)) - Perl_sv_catpvf(aTHX_ where_sv, "%c", yychar); + else if (isPRINT_LC(yychar)) { + const char string = yychar; + sv_catpvn(where_sv, &string, 1); + } else Perl_sv_catpvf(aTHX_ where_sv, "\\%03o", yychar & 255); where = SvPVX_const(where_sv); @@ -12535,8 +12671,10 @@ Perl_yyerror(pTHX_ const char *s) (int)PL_multi_open,(int)PL_multi_close,(IV)PL_multi_start); PL_multi_end = 0; } - if (PL_in_eval & EVAL_WARNONLY && ckWARN_d(WARN_SYNTAX)) - Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "%"SVf, SVfARG(msg)); + if (PL_in_eval & EVAL_WARNONLY) { + if (ckWARN_d(WARN_SYNTAX)) + Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "%"SVf, SVfARG(msg)); + } else qerror(msg); if (PL_error_count >= 10) { @@ -12560,6 +12698,9 @@ S_swallow_bom(pTHX_ U8 *s) { dVAR; const STRLEN slen = SvCUR(PL_linestr); + + PERL_ARGS_ASSERT_SWALLOW_BOM; + switch (s[0]) { case 0xFF: if (s[1] == 0xFE) { @@ -12668,23 +12809,6 @@ S_swallow_bom(pTHX_ U8 *s) return (char*)s; } -/* - * restore_rsfp - * Restore a source filter. - */ - -static void -restore_rsfp(pTHX_ void *f) -{ - dVAR; - PerlIO * const fp = (PerlIO*)f; - - if (PL_rsfp == PerlIO_stdin()) - PerlIO_clearerr(PL_rsfp); - else if (PL_rsfp && (PL_rsfp != fp)) - PerlIO_close(PL_rsfp); - PL_rsfp = fp; -} #ifndef PERL_NO_UTF16_FILTER static I32 @@ -12750,11 +12874,14 @@ passed in, for performance reasons. */ char * -Perl_scan_vstring(pTHX_ const char *s, const char *e, SV *sv) +Perl_scan_vstring(pTHX_ const char *s, const char *const e, SV *sv) { dVAR; const char *pos = s; const char *start = s; + + PERL_ARGS_ASSERT_SCAN_VSTRING; + if (*pos == 'v') pos++; /* get past 'v' */ while (pos < e && (isDIGIT(*pos) || *pos == '_')) pos++; @@ -12776,7 +12903,7 @@ Perl_scan_vstring(pTHX_ const char *s, const char *e, SV *sv) if (*s == 'v') s++; /* get past 'v' */ - sv_setpvn(sv, "", 0); + sv_setpvs(sv, ""); for (;;) { /* this is atoi() that tolerates underscores */