X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/77ca0c92d2c0e47301d906d355d9ab3afb6f6bcb..6d0f518e0b7ff19ca6956aba9c075bcc87b59d84:/toke.c?ds=sidebyside diff --git a/toke.c b/toke.c index 8777426..3410ab5 100644 --- a/toke.c +++ b/toke.c @@ -1,6 +1,6 @@ /* toke.c * - * Copyright (c) 1991-1999, Larry Wall + * Copyright (c) 1991-2000, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -28,22 +28,12 @@ static char ident_too_long[] = "Identifier too long"; static void restore_rsfp(pTHXo_ void *f); -static void restore_expect(pTHXo_ void *e); -static void restore_lex_expect(pTHXo_ void *e); +#define XFAKEBRACK 128 +#define XENUMMASK 127 + +/*#define UTF (SvUTF8(PL_linestr) && !(PL_hints & HINT_BYTE))*/ #define UTF (PL_hints & HINT_UTF8) -/* - * Note: we try to be careful never to call the isXXX_utf8() functions - * unless we're pretty sure we've seen the beginning of a UTF-8 character - * (that is, the two high bits are set). Otherwise we risk loading in the - * heavy-duty SWASHINIT and SWASHGET routines unnecessarily. - */ -#define isIDFIRST_lazy(p) ((!UTF || (*((U8*)p) < 0xc0)) \ - ? isIDFIRST(*(p)) \ - : isIDFIRST_utf8((U8*)p)) -#define isALNUM_lazy(p) ((!UTF || (*((U8*)p) < 0xc0)) \ - ? isALNUM(*(p)) \ - : isALNUM_utf8((U8*)p)) /* In variables name $^X, these are the legal values for X. * 1999-02-27 mjd-perl-patch@plover.com */ @@ -104,7 +94,7 @@ int* yychar_pointer = NULL; #ifdef CLINE #undef CLINE #endif -#define CLINE (PL_copline = (PL_curcop->cop_line < PL_copline ? PL_curcop->cop_line : PL_copline)) +#define CLINE (PL_copline = (CopLINE(PL_curcop) < PL_copline ? CopLINE(PL_curcop) : PL_copline)) /* * Convenience functions to return different tokens and prime the @@ -120,7 +110,7 @@ int* yychar_pointer = NULL; * LOOPX : loop exiting command (goto, last, dump, etc) * FTST : file test operator * FUN0 : zero-argument function - * FUN1 : not used + * FUN1 : not used, except for not, which isn't a UNIOP * BOop : bitwise or or xor * BAop : bitwise and * SHop : shift operator @@ -222,9 +212,9 @@ S_no_op(pTHX_ char *what, char *s) yywarn(Perl_form(aTHX_ "%s found where operator expected", what)); if (is_first) Perl_warn(aTHX_ "\t(Missing semicolon on previous line?)\n"); - else if (PL_oldoldbufptr && isIDFIRST_lazy(PL_oldoldbufptr)) { + else if (PL_oldoldbufptr && isIDFIRST_lazy_if(PL_oldoldbufptr,UTF)) { char *t; - for (t = PL_oldoldbufptr; *t && (isALNUM_lazy(t) || *t == ':'); t++) ; + for (t = PL_oldoldbufptr; *t && (isALNUM_lazy_if(t,UTF) || *t == ':'); t++) ; if (t < PL_bufptr && isSPACE(*t)) Perl_warn(aTHX_ "\t(Do you need to predeclare %.*s?)\n", t - PL_oldoldbufptr, PL_oldoldbufptr); @@ -303,15 +293,36 @@ S_depcom(pTHX) * utf16-to-utf8-reversed. */ -#ifdef WIN32 +#ifdef PERL_CR_FILTER +static void +strip_return(SV *sv) +{ + register char *s = SvPVX(sv); + register char *e = s + SvCUR(sv); + /* outer loop optimized to do nothing if there are no CR-LFs */ + while (s < e) { + if (*s++ == '\r' && *s == '\n') { + /* hit a CR-LF, need to copy the rest */ + register char *d = s - 1; + *d++ = *s++; + while (s < e) { + if (*s == '\r' && s[1] == '\n') + s++; + *d++ = *s++; + } + SvCUR(sv) -= s - d; + return; + } + } +} STATIC I32 -S_win32_textfilter(pTHX_ int idx, SV *sv, int maxlen) +S_cr_textfilter(pTHX_ int idx, SV *sv, int maxlen) { - I32 count = FILTER_READ(idx+1, sv, maxlen); - if (count > 0 && !maxlen) - win32_strip_return(sv); - return count; + I32 count = FILTER_READ(idx+1, sv, maxlen); + if (count > 0 && !maxlen) + strip_return(sv); + return count; } #endif @@ -360,13 +371,21 @@ Perl_lex_start(pTHX_ SV *line) SAVEI32(PL_lex_dojoin); SAVEI32(PL_lex_brackets); - SAVEI32(PL_lex_fakebrack); SAVEI32(PL_lex_casemods); SAVEI32(PL_lex_starts); SAVEI32(PL_lex_state); - SAVESPTR(PL_lex_inpat); + SAVEVPTR(PL_lex_inpat); SAVEI32(PL_lex_inwhat); - SAVEI16(PL_curcop->cop_line); + if (PL_lex_state == LEX_KNOWNEXT) { + I32 toke = PL_nexttoke; + while (--toke >= 0) { + SAVEI32(PL_nexttype[toke]); + SAVEVPTR(PL_nextval[toke]); + } + SAVEI32(PL_nexttoke); + PL_nexttoke = 0; + } + SAVECOPLINE(PL_curcop); SAVEPPTR(PL_bufptr); SAVEPPTR(PL_bufend); SAVEPPTR(PL_oldbufptr); @@ -375,19 +394,18 @@ Perl_lex_start(pTHX_ SV *line) SAVESPTR(PL_linestr); SAVEPPTR(PL_lex_brackstack); SAVEPPTR(PL_lex_casestack); - SAVEDESTRUCTOR(restore_rsfp, PL_rsfp); + SAVEDESTRUCTOR_X(restore_rsfp, PL_rsfp); SAVESPTR(PL_lex_stuff); SAVEI32(PL_lex_defer); SAVEI32(PL_sublex_info.sub_inwhat); SAVESPTR(PL_lex_repl); - SAVEDESTRUCTOR(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */ - SAVEDESTRUCTOR(restore_lex_expect, PL_tokenbuf + PL_expect); + SAVEINT(PL_expect); + SAVEINT(PL_lex_expect); PL_lex_state = LEX_NORMAL; PL_lex_defer = 0; PL_expect = XSTATE; PL_lex_brackets = 0; - PL_lex_fakebrack = 0; New(899, PL_lex_brackstack, 120, char); New(899, PL_lex_casestack, 12, char); SAVEFREEPV(PL_lex_brackstack); @@ -434,7 +452,7 @@ Perl_lex_end(pTHX) * S_incline * This subroutine has nothing to do with tilting, whether at windmills * or pinball tables. Its name is short for "increment line". It - * increments the current line number in PL_curcop->cop_line and checks + * increments the current line number in CopLINE(PL_curcop) and checks * to see whether the line starts with a comment of the form * # line 500 "foo.pm" * If so, it sets the current line number and file to the values in the comment. @@ -449,7 +467,7 @@ S_incline(pTHX_ char *s) char ch; int sawline = 0; - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); if (*s++ != '#') return; while (*s == ' ' || *s == '\t') s++; @@ -474,11 +492,9 @@ S_incline(pTHX_ char *s) ch = *t; *t = '\0'; if (t - s > 0) - PL_curcop->cop_filegv = gv_fetchfile(s); - else - PL_curcop->cop_filegv = gv_fetchfile(PL_origfilename); + CopFILE_set(PL_curcop, s); *t = ch; - PL_curcop->cop_line = atoi(n)-1; + CopLINE_set(PL_curcop, atoi(n)-1); } /* @@ -590,7 +606,7 @@ S_skipspace(pTHX_ register char *s) sv_upgrade(sv, SVt_PVMG); sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr); - av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv); + av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv); } } } @@ -615,7 +631,7 @@ S_check_uni(pTHX) return; while (isSPACE(*PL_last_uni)) PL_last_uni++; - for (s = PL_last_uni; isALNUM_lazy(s) || *s == '-'; s++) ; + for (s = PL_last_uni; isALNUM_lazy_if(s,UTF) || *s == '-'; s++) ; if ((t = strchr(s, '(')) && t < PL_bufptr) return; if (ckWARN_d(WARN_AMBIGUOUS)){ @@ -673,7 +689,7 @@ S_uni(pTHX_ I32 f, char *s) */ STATIC I32 -S_lop(pTHX_ I32 f, expectation x, char *s) +S_lop(pTHX_ I32 f, int x, char *s) { dTHR; yylval.ival = f; @@ -738,7 +754,7 @@ S_force_word(pTHX_ register char *start, int token, int check_keyword, int allow start = skipspace(start); s = start; - if (isIDFIRST_lazy(s) || + if (isIDFIRST_lazy_if(s,UTF) || (allow_pack && *s == ':') || (allow_initial_tick && *s == '\'') ) { @@ -804,13 +820,12 @@ S_force_version(pTHX_ char *s) s = skipspace(s); - /* default VERSION number -- GBARR */ - - if(isDIGIT(*s)) { - char *d; - int c; - for( d=s, c = 1; isDIGIT(*d) || *d == '_' || (*d == '.' && c--); d++); - if((*d == ';' || isSPACE(*d)) && *(skipspace(d)) != ',') { + if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) { + char *d = s; + if (*d == 'v') + d++; + for (; isDIGIT(*d) || *d == '_' || *d == '.'; d++); + if ((*d == ';' || isSPACE(*d)) && *(skipspace(d)) != ',') { s = scan_num(s); /* real VERSION number -- GBARR */ version = yylval.opval; @@ -963,13 +978,12 @@ S_sublex_push(pTHX) PL_lex_state = PL_sublex_info.super_state; SAVEI32(PL_lex_dojoin); SAVEI32(PL_lex_brackets); - SAVEI32(PL_lex_fakebrack); SAVEI32(PL_lex_casemods); SAVEI32(PL_lex_starts); SAVEI32(PL_lex_state); - SAVESPTR(PL_lex_inpat); + SAVEVPTR(PL_lex_inpat); SAVEI32(PL_lex_inwhat); - SAVEI16(PL_curcop->cop_line); + SAVECOPLINE(PL_curcop); SAVEPPTR(PL_bufptr); SAVEPPTR(PL_oldbufptr); SAVEPPTR(PL_oldoldbufptr); @@ -988,7 +1002,6 @@ S_sublex_push(pTHX) PL_lex_dojoin = FALSE; PL_lex_brackets = 0; - PL_lex_fakebrack = 0; New(899, PL_lex_brackstack, 120, char); New(899, PL_lex_casestack, 12, char); SAVEFREEPV(PL_lex_brackstack); @@ -997,7 +1010,7 @@ S_sublex_push(pTHX) *PL_lex_casestack = '\0'; PL_lex_starts = 0; PL_lex_state = LEX_INTERPCONCAT; - PL_curcop->cop_line = PL_multi_start; + CopLINE_set(PL_curcop, 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) @@ -1036,7 +1049,6 @@ S_sublex_done(pTHX) SAVEFREESV(PL_linestr); PL_lex_dojoin = FALSE; PL_lex_brackets = 0; - PL_lex_fakebrack = 0; PL_lex_casemods = 0; *PL_lex_casestack = '\0'; PL_lex_starts = 0; @@ -1145,6 +1157,7 @@ S_scan_const(pTHX_ char *start) register char *s = start; /* start of the constant */ register char *d = SvPVX(sv); /* destination for copies */ bool dorange = FALSE; /* are we in a translit range? */ + bool has_utf = FALSE; /* embedded \x{} */ I32 len; /* ? */ I32 utf = (PL_lex_inwhat == OP_TRANS && PL_sublex_info.sub_op) ? (PL_sublex_info.sub_op->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) @@ -1153,7 +1166,7 @@ S_scan_const(pTHX_ char *start) ? (PL_sublex_info.sub_op->op_private & (PL_lex_repl ? OPpTRANS_FROM_UTF : OPpTRANS_TO_UTF)) : UTF; - char *leaveit = /* set of acceptably-backslashed characters */ + const char *leaveit = /* set of acceptably-backslashed characters */ PL_lex_inpat ? "\\.^$@AGZdDwWsSbBpPXC+*?|()-nrtfeaxcz0123456789[{]} \t\n\r\f\v#" : ""; @@ -1250,7 +1263,8 @@ S_scan_const(pTHX_ char *start) } /* check for embedded arrays (@foo, @:foo, @'foo, @{foo}, @$foo) */ - else if (*s == '@' && s[1] && (isALNUM_lazy(s+1) || strchr(":'{$", s[1]))) + else if (*s == '@' && s[1] + && (isALNUM_lazy_if(s+1,UTF) || strchr(":'{$", s[1]))) break; /* check for embedded scalars. only stop if we're sure it's a @@ -1270,11 +1284,14 @@ S_scan_const(pTHX_ char *start) if (ckWARN(WARN_UTF8)) { (void)utf8_to_uv((U8*)s, &len); /* could cvt latin-1 to utf8 here... */ if (len) { + has_utf = TRUE; while (len--) *d++ = *s++; continue; } } + else + has_utf = TRUE; /* assume valid utf8 */ } /* backslashes */ @@ -1330,7 +1347,7 @@ S_scan_const(pTHX_ char *start) /* \132 indicates an octal constant */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': - *d++ = scan_oct(s, 3, &len); + *d++ = (char)scan_oct(s, 3, &len); s += len; continue; @@ -1344,16 +1361,11 @@ S_scan_const(pTHX_ char *start) yyerror("Missing right brace on \\x{}"); e = s; } - if (!utf) { - dTHR; - if (ckWARN(WARN_UTF8)) - Perl_warner(aTHX_ WARN_UTF8, - "Use of \\x{} without utf8 declaration"); - } /* note: utf always shorter than hex */ d = (char*)uv_to_utf8((U8*)d, - scan_hex(s + 1, e - s - 1, &len)); + (UV)scan_hex(s + 1, e - s - 1, &len)); s = e + 1; + has_utf = TRUE; } else { UV uv = (UV)scan_hex(s, 2, &len); @@ -1361,6 +1373,7 @@ S_scan_const(pTHX_ char *start) utf != (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) { d = (char*)uv_to_utf8((U8*)d, uv); /* doing a CU or UC */ + has_utf = TRUE; } else { if (uv >= 127 && UTF) { @@ -1368,7 +1381,7 @@ S_scan_const(pTHX_ char *start) if (ckWARN(WARN_UTF8)) Perl_warner(aTHX_ WARN_UTF8, "\\x%.*s will produce malformed UTF-8 character; use \\x{%.*s} for that", - len,s,len,s); + (int)len,s,(int)len,s); } *d++ = (char)uv; } @@ -1471,6 +1484,8 @@ S_scan_const(pTHX_ char *start) *d = '\0'; SvCUR_set(sv, d - SvPVX(sv)); SvPOK_on(sv); + if (has_utf) + SvUTF8_on(sv); /* shrink the sv if we allocated more than we used */ if (SvCUR(sv) + 5 < SvLEN(sv)) { @@ -1579,7 +1594,7 @@ S_intuit_more(pTHX_ register char *s) case '&': case '$': weight -= seen[un_char] * 10; - if (isALNUM_lazy(s+1)) { + if (isALNUM_lazy_if(s+1,UTF)) { scan_ident(s, send, tmpbuf, sizeof tmpbuf, FALSE); if ((int)strlen(tmpbuf) > 1 && gv_fetchpv(tmpbuf,FALSE, SVt_PV)) weight -= 100; @@ -1663,7 +1678,7 @@ S_intuit_more(pTHX_ register char *s) * 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 a filehandle or package, but is quotd with + * Not a method if bar is a filehandle or package, but is quoted with * => */ @@ -1764,7 +1779,8 @@ S_incl_perldb(pTHX) * store private buffers and state information. * * The supplied datasv parameter is upgraded to a PVIO type - * and the IoDIRP field is used to store the function pointer. + * and the IoDIRP field is used to store the function pointer, + * and IOf_FAKE_DIRP is enabled on datasv to mark this as such. * Note that IoTOP_NAME, IoFMT_NAME, IoBOTTOM_NAME, if set for * private use must be set using malloc'd pointers. */ @@ -1772,10 +1788,9 @@ S_incl_perldb(pTHX) SV * Perl_filter_add(pTHX_ filter_t funcp, SV *datasv) { - if (!funcp){ /* temporary handy debugging hack to be deleted */ - PL_filter_debug = atoi((char*)datasv); - return NULL; - } + if (!funcp) + return Nullsv; + if (!PL_rsfp_filters) PL_rsfp_filters = newAV(); if (!datasv) @@ -1783,12 +1798,9 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv) if (!SvUPGRADE(datasv, SVt_PVIO)) Perl_die(aTHX_ "Can't upgrade filter_add data to SVt_PVIO"); IoDIRP(datasv) = (DIR*)funcp; /* stash funcp into spare field */ -#ifdef DEBUGGING - if (PL_filter_debug) { - STRLEN n_a; - Perl_warn(aTHX_ "filter_add func %p (%s)", funcp, SvPV(datasv, n_a)); - } -#endif /* DEBUGGING */ + IoFLAGS(datasv) |= IOf_FAKE_DIRP; + DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_add func %p (%s)\n", + funcp, SvPV_nolen(datasv))); av_unshift(PL_rsfp_filters, 1); av_store(PL_rsfp_filters, 0, datasv) ; return(datasv); @@ -1799,15 +1811,15 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv) void Perl_filter_del(pTHX_ filter_t funcp) { -#ifdef DEBUGGING - if (PL_filter_debug) - Perl_warn(aTHX_ "filter_del func %p", funcp); -#endif /* DEBUGGING */ + SV *datasv; + DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p", funcp)); if (!PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0) return; /* if filter is on top of stack (usual case) just pop it off */ - if (IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) == (DIR*)funcp){ - IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) = NULL; + datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters)); + if (IoDIRP(datasv) == (DIR*)funcp) { + IoFLAGS(datasv) &= ~IOf_FAKE_DIRP; + IoDIRP(datasv) = (DIR*)NULL; sv_free(av_pop(PL_rsfp_filters)); return; @@ -1832,10 +1844,8 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen) if (idx > AvFILLp(PL_rsfp_filters)){ /* Any more filters? */ /* Provide a default input filter to make life easy. */ /* Note that we append to the line. This is handy. */ -#ifdef DEBUGGING - if (PL_filter_debug) - Perl_warn(aTHX_ "filter_read %d: from rsfp\n", idx); -#endif /* DEBUGGING */ + DEBUG_P(PerlIO_printf(Perl_debug_log, + "filter_read %d: from rsfp\n", idx)); if (maxlen) { /* Want a block */ int len ; @@ -1863,21 +1873,16 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen) } /* Skip this filter slot if filter has been deleted */ if ( (datasv = FILTER_DATA(idx)) == &PL_sv_undef){ -#ifdef DEBUGGING - if (PL_filter_debug) - Perl_warn(aTHX_ "filter_read %d: skipped (filter deleted)\n", idx); -#endif /* DEBUGGING */ + DEBUG_P(PerlIO_printf(Perl_debug_log, + "filter_read %d: skipped (filter deleted)\n", + idx)); return FILTER_READ(idx+1, buf_sv, maxlen); /* recurse */ } /* Get function pointer hidden within datasv */ funcp = (filter_t)IoDIRP(datasv); -#ifdef DEBUGGING - if (PL_filter_debug) { - STRLEN n_a; - Perl_warn(aTHX_ "filter_read %d: via function %p (%s)\n", - idx, funcp, SvPV(datasv,n_a)); - } -#endif /* DEBUGGING */ + DEBUG_P(PerlIO_printf(Perl_debug_log, + "filter_read %d: via function %p (%s)\n", + idx, funcp, SvPV_nolen(datasv))); /* Call function. The function is expected to */ /* call "FILTER_READ(idx+1, buf_sv)" first. */ /* Return: <0:error, =0:eof, >0:not eof */ @@ -1887,9 +1892,9 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen) STATIC char * S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append) { -#ifdef WIN32FILTER +#ifdef PERL_CR_FILTER if (!PL_rsfp_filters) { - filter_add(win32_textfilter,NULL); + filter_add(S_cr_textfilter,NULL); } #endif if (PL_rsfp_filters) { @@ -1972,6 +1977,10 @@ Perl_yylex(pTHX) */ if (PL_in_my) { if (PL_in_my == KEY_our) { /* "our" is merely analogous to "my" */ + if (strchr(PL_tokenbuf,':')) + yyerror(Perl_form(aTHX_ "No package name allowed for " + "variable %s in \"our\"", + PL_tokenbuf)); tmp = pad_allocmy(PL_tokenbuf); } else { @@ -2009,15 +2018,19 @@ Perl_yylex(pTHX) } #endif /* USE_THREADS */ if ((tmp = pad_findmy(PL_tokenbuf)) != NOT_IN_PAD) { + SV *namesv = AvARRAY(PL_comppad_name)[tmp]; /* might be an "our" variable" */ - if (SvFLAGS(AvARRAY(PL_comppad_name)[tmp]) & SVpad_OUR) { + if (SvFLAGS(namesv) & SVpad_OUR) { /* build ops for a bareword */ - yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf+1, 0)); + SV *sym = newSVpv(HvNAME(GvSTASH(namesv)),0); + sv_catpvn(sym, "::", 2); + sv_catpv(sym, PL_tokenbuf+1); + yylval.opval = (OP*)newSVOP(OP_CONST, 0, sym); yylval.opval->op_private = OPpCONST_ENTERED; - gv_fetchpv(PL_tokenbuf+1, + gv_fetchpv(SvPVX(sym), (PL_in_eval - ? (GV_ADDMULTI | GV_ADDINEVAL | GV_ADDOUR) - : GV_ADDOUR + ? (GV_ADDMULTI | GV_ADDINEVAL) + : TRUE ), ((PL_tokenbuf[0] == '$') ? SVt_PV : (PL_tokenbuf[0] == '@') ? SVt_PVAV @@ -2266,13 +2279,14 @@ Perl_yylex(pTHX) PL_oldoldbufptr = PL_oldbufptr; PL_oldbufptr = s; DEBUG_p( { - PerlIO_printf(PerlIO_stderr(), "### Tokener expecting %s at %s\n", exp_name[PL_expect], s); + PerlIO_printf(Perl_debug_log, "### Tokener expecting %s at %s\n", + exp_name[PL_expect], s); } ) retry: switch (*s) { default: - if (isIDFIRST_lazy(s)) + if (isIDFIRST_lazy_if(s,UTF)) goto keylookup; Perl_croak(aTHX_ "Unrecognized character \\x%02X", *s & 255); case 4: @@ -2344,7 +2358,7 @@ Perl_yylex(pTHX) sv_upgrade(sv, SVt_PVMG); sv_setsv(sv,PL_linestr); - av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv); + av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv); } goto retry; } @@ -2393,10 +2407,10 @@ Perl_yylex(pTHX) sv_upgrade(sv, SVt_PVMG); sv_setsv(sv,PL_linestr); - av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv); + av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv); } PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); - if (PL_curcop->cop_line == 1) { + if (CopLINE(PL_curcop) == 1) { while (s < PL_bufend && isSPACE(*s)) s++; if (*s == ':' && s[1] != ':') /* for csh execing sh scripts */ @@ -2434,7 +2448,7 @@ Perl_yylex(pTHX) */ SV *x = GvSV(gv_fetchpv("\030", TRUE, SVt_PV)); assert(SvPOK(x) || SvGMAGICAL(x)); - if (sv_eq(x, GvSV(PL_curcop->cop_filegv))) { + if (sv_eq(x, CopFILESV(PL_curcop))) { sv_setpvn(x, ipath, ipathend - ipath); SvSETMAGIC(x); } @@ -2640,7 +2654,7 @@ Perl_yylex(pTHX) else if (*s == '>') { s++; s = skipspace(s); - if (isIDFIRST_lazy(s)) { + if (isIDFIRST_lazy_if(s,UTF)) { s = force_word(s,METHOD,FALSE,TRUE,FALSE); TOKEN(ARROW); } @@ -2736,8 +2750,23 @@ Perl_yylex(pTHX) grabattrs: s = skipspace(s); attrs = Nullop; - while (isIDFIRST_lazy(s)) { + while (isIDFIRST_lazy_if(s,UTF)) { d = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, FALSE, &len); + if (isLOWER(*s) && (tmp = keyword(PL_tokenbuf, len))) { + if (tmp < 0) tmp = -tmp; + switch (tmp) { + case KEY_or: + case KEY_and: + case KEY_for: + case KEY_unless: + case KEY_if: + case KEY_while: + case KEY_until: + goto got_attrs; + default: + break; + } + } if (*d == '(') { d = scan_str(d,TRUE,TRUE); if (!d) { @@ -2769,11 +2798,13 @@ Perl_yylex(pTHX) newSVpvn(s, len))); } s = skipspace(d); - while (*s == ',') + if (*s == ':' && s[1] != ':') s = skipspace(s+1); + else if (s == d) + break; /* require real whitespace or :'s */ } - tmp = (PL_expect == XOPERATOR ? '=' : '{'); /*'}' for vi */ - if (*s != ';' && *s != tmp) { + tmp = (PL_expect == XOPERATOR ? '=' : '{'); /*'}(' for vi */ + if (*s != ';' && *s != tmp && (tmp != '=' || *s != ')')) { char q = ((*s == '\'') ? '"' : '\''); /* If here for an expression, and parsed no attrs, back off. */ if (tmp == '=' && !attrs) { @@ -2793,6 +2824,7 @@ Perl_yylex(pTHX) op_free(attrs); OPERATOR(':'); } + got_attrs: if (attrs) { PL_nextval[PL_nexttoke].opval = attrs; force_next(THING); @@ -2808,8 +2840,8 @@ Perl_yylex(pTHX) PL_expect = XTERM; TOKEN('('); case ';': - if (PL_curcop->cop_line < PL_copline) - PL_copline = PL_curcop->cop_line; + if (CopLINE(PL_curcop) < PL_copline) + PL_copline = CopLINE(PL_curcop); tmp = *s++; OPERATOR(tmp); case ')': @@ -2863,7 +2895,7 @@ Perl_yylex(pTHX) while (d < PL_bufend && (*d == ' ' || *d == '\t')) d++; } - if (d < PL_bufend && isIDFIRST_lazy(d)) { + if (d < PL_bufend && isIDFIRST_lazy_if(d,UTF)) { d = scan_word(d, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1, FALSE, &len); while (d < PL_bufend && (*d == ' ' || *d == '\t')) @@ -2922,7 +2954,8 @@ Perl_yylex(pTHX) if (++t < PL_bufend && (!isALNUM(*t) || ((*t == 'q' || *t == 'x') && ++t < PL_bufend - && !isALNUM(*t)))) { + && !isALNUM(*t)))) + { char *tmps; char open, close, term; I32 brackets = 1; @@ -2953,8 +2986,10 @@ Perl_yylex(pTHX) } t++; } - else if (isIDFIRST_lazy(s)) { - for (t++; t < PL_bufend && isALNUM_lazy(t); t++) ; + else if (isALNUM_lazy_if(t,UTF)) { + t += UTF8SKIP(t); + while (t < PL_bufend && isALNUM_lazy_if(t,UTF)) + t += UTF8SKIP(t); } while (t < PL_bufend && isSPACE(*t)) t++; @@ -2972,7 +3007,7 @@ Perl_yylex(pTHX) } break; } - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); if (isSPACE(*s) || *s == '#') PL_copline = NOLINE; /* invalidate current command line number */ TOKEN('{'); @@ -2987,7 +3022,8 @@ Perl_yylex(pTHX) PL_lex_formbrack = 0; if (PL_lex_state == LEX_INTERPNORMAL) { if (PL_lex_brackets == 0) { - if (PL_lex_fakebrack) { + if (PL_expect & XFAKEBRACK) { + PL_expect &= XENUMMASK; PL_lex_state = LEX_INTERPEND; PL_bufptr = s; return yylex(); /* ignore fake brackets */ @@ -2998,9 +3034,9 @@ Perl_yylex(pTHX) PL_lex_state = LEX_INTERPEND; } } - if (PL_lex_brackets < PL_lex_fakebrack) { + if (PL_expect & XFAKEBRACK) { + PL_expect &= XENUMMASK; PL_bufptr = s; - PL_lex_fakebrack = 0; return yylex(); /* ignore fake brackets */ } force_next('}'); @@ -3012,10 +3048,12 @@ Perl_yylex(pTHX) AOPERATOR(ANDAND); s--; if (PL_expect == XOPERATOR) { - if (ckWARN(WARN_SEMICOLON) && isIDFIRST_lazy(s) && PL_bufptr == PL_linestart) { - PL_curcop->cop_line--; + if (ckWARN(WARN_SEMICOLON) + && isIDFIRST_lazy_if(s,UTF) && PL_bufptr == PL_linestart) + { + CopLINE_dec(PL_curcop); Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi); - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); } BAop(OP_BIT_AND); } @@ -3142,7 +3180,7 @@ Perl_yylex(pTHX) } } - if (s[1] == '#' && (isIDFIRST_lazy(s+2) || strchr("{$:+-", s[2]))) { + if (s[1] == '#' && (isIDFIRST_lazy_if(s+2,UTF) || strchr("{$:+-", s[2]))) { PL_tokenbuf[0] = '@'; s = scan_ident(s + 1, PL_bufend, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1, FALSE); @@ -3185,7 +3223,7 @@ Perl_yylex(pTHX) PL_tokenbuf[0] = '@'; if (ckWARN(WARN_SYNTAX)) { for(t = s + 1; - isSPACE(*t) || isALNUM_lazy(t) || *t == '$'; + isSPACE(*t) || isALNUM_lazy_if(t,UTF) || *t == '$'; t++) ; if (*t++ == ',') { PL_bufptr = skipspace(PL_bufptr); @@ -3205,7 +3243,7 @@ Perl_yylex(pTHX) char tmpbuf[sizeof PL_tokenbuf]; STRLEN len; for (t++; isSPACE(*t); t++) ; - if (isIDFIRST_lazy(t)) { + if (isIDFIRST_lazy_if(t,UTF)) { t = scan_word(t, tmpbuf, sizeof tmpbuf, TRUE, &len); for (; isSPACE(*t); t++) ; if (*t == ';' && get_cv(tmpbuf, FALSE)) @@ -3223,9 +3261,9 @@ Perl_yylex(pTHX) PL_expect = XOPERATOR; else if (strchr("$@\"'`q", *s)) PL_expect = XTERM; /* e.g. print $fh "foo" */ - else if (strchr("&*<%", *s) && isIDFIRST_lazy(s+1)) + else if (strchr("&*<%", *s) && isIDFIRST_lazy_if(s+1,UTF)) PL_expect = XTERM; /* e.g. print $fh &sub */ - else if (isIDFIRST_lazy(s)) { + else if (isIDFIRST_lazy_if(s,UTF)) { char tmpbuf[sizeof PL_tokenbuf]; scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len); if (tmp = keyword(tmpbuf, len)) { @@ -3283,7 +3321,7 @@ Perl_yylex(pTHX) if (ckWARN(WARN_SYNTAX)) { if (*s == '[' || *s == '{') { char *t = s + 1; - while (*t && (isALNUM_lazy(t) || strchr(" \t$#+-'\"", *t))) + while (*t && (isALNUM_lazy_if(t,UTF) || strchr(" \t$#+-'\"", *t))) t++; if (*t == '}' || *t == ']') { t++; @@ -3304,7 +3342,8 @@ Perl_yylex(pTHX) /* 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(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()); @@ -3408,6 +3447,19 @@ Perl_yylex(pTHX) no_op("Backslash",s); OPERATOR(REFGEN); + case 'v': + if (isDIGIT(s[1]) && PL_expect == XTERM) { + char *start = s; + start++; + start++; + while (isDIGIT(*start)) + start++; + if (*start == '.' && isDIGIT(start[1])) { + s = scan_num(s); + TERM(THING); + } + } + goto keylookup; case 'x': if (isDIGIT(s[1]) && PL_expect == XOPERATOR) { s++; @@ -3437,7 +3489,7 @@ Perl_yylex(pTHX) case 's': case 'S': case 't': case 'T': case 'u': case 'U': - case 'v': case 'V': + case 'V': case 'w': case 'W': case 'X': case 'y': case 'Y': @@ -3511,6 +3563,7 @@ Perl_yylex(pTHX) } else if (gv && !gvp && -tmp==KEY_lock /* XXX generalizable kludge */ + && GvCVu(gv) && !hv_fetch(GvHVn(PL_incgv), "Thread.pm", 9, FALSE)) { tmp = 0; /* any sub overrides "weak" keyword */ @@ -3549,9 +3602,9 @@ Perl_yylex(pTHX) if (PL_expect == XOPERATOR) { if (PL_bufptr == PL_linestart) { - PL_curcop->cop_line--; + CopLINE_dec(PL_curcop); Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi); - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); } else no_op("Bareword",s); @@ -3603,7 +3656,8 @@ Perl_yylex(pTHX) if (PL_oldoldbufptr && PL_oldoldbufptr < PL_bufptr && - (PL_oldoldbufptr == PL_last_lop || PL_oldoldbufptr == PL_last_uni) && + (PL_oldoldbufptr == PL_last_lop + || PL_oldoldbufptr == PL_last_uni) && /* NO SKIPSPACE BEFORE HERE! */ (PL_expect == XREF || ((PL_opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF)) @@ -3615,7 +3669,7 @@ Perl_yylex(pTHX) /* Two barewords in a row may indicate method call. */ - if ((isIDFIRST_lazy(s) || *s == '$') && (tmp=intuit_method(s,gv))) + if ((isIDFIRST_lazy_if(s,UTF) || *s == '$') && (tmp=intuit_method(s,gv))) return tmp; /* If not a declared subroutine, it's an indirect object. */ @@ -3661,7 +3715,7 @@ Perl_yylex(pTHX) /* If followed by a bareword, see if it looks like indir obj. */ - if ((isIDFIRST_lazy(s) || *s == '$') && (tmp = intuit_method(s,gv))) + if ((isIDFIRST_lazy_if(s,UTF) || *s == '$') && (tmp = intuit_method(s,gv))) return tmp; /* Not a method, so call it a subroutine (if defined) */ @@ -3737,17 +3791,12 @@ Perl_yylex(pTHX) case KEY___FILE__: yylval.opval = (OP*)newSVOP(OP_CONST, 0, - newSVsv(GvSV(PL_curcop->cop_filegv))); + newSVpv(CopFILE(PL_curcop),0)); TERM(THING); case KEY___LINE__: -#ifdef IV_IS_QUAD yylval.opval = (OP*)newSVOP(OP_CONST, 0, - Perl_newSVpvf(aTHX_ "%" PERL_PRId64, (IV)PL_curcop->cop_line)); -#else - yylval.opval = (OP*)newSVOP(OP_CONST, 0, - Perl_newSVpvf(aTHX_ "%ld", (long)PL_curcop->cop_line)); -#endif + Perl_newSVpvf(aTHX_ "%"IVdf, (IV)CopLINE(PL_curcop))); TERM(THING); case KEY___PACKAGE__: @@ -3785,6 +3834,28 @@ Perl_yylex(pTHX) IoTYPE(GvIOp(gv)) = '-'; else IoTYPE(GvIOp(gv)) = '<'; +#if defined(WIN32) && !defined(PERL_TEXTMODE_SCRIPTS) + /* if the script was opened in binmode, we need to revert + * it to text mode for compatibility; but only iff it has CRs + * XXX this is a questionable hack at best. */ + if (PL_bufend-PL_bufptr > 2 + && PL_bufend[-1] == '\n' && PL_bufend[-2] == '\r') + { + Off_t loc = 0; + if (IoTYPE(GvIOp(gv)) == '<') { + loc = PerlIO_tell(PL_rsfp); + (void)PerlIO_seek(PL_rsfp, 0L, 0); + } + if (PerlLIO_setmode(PerlIO_fileno(PL_rsfp), O_TEXT) != -1) { +#if defined(__BORLANDC__) + /* XXX see note in do_binmode() */ + ((FILE*)PL_rsfp)->flags |= _F_BIN; +#endif + if (loc > 0) + PerlIO_seek(PL_rsfp, loc, 0); + } + } +#endif PL_rsfp = Nullfp; } goto fake_eof; @@ -3793,8 +3864,9 @@ Perl_yylex(pTHX) case KEY_AUTOLOAD: case KEY_DESTROY: case KEY_BEGIN: - case KEY_END: + case KEY_CHECK: case KEY_INIT: + case KEY_END: if (PL_expect == XSTATE) { s = PL_bufptr; goto really_sub; @@ -3861,8 +3933,10 @@ Perl_yylex(pTHX) case KEY_crypt: #ifdef FCRYPT - if (!PL_cryptseen++) + if (!PL_cryptseen) { + PL_cryptseen = TRUE; init_des(); + } #endif LOP(OP_CRYPT,XTERM); @@ -3923,7 +3997,7 @@ Perl_yylex(pTHX) PREBLOCK(ELSE); case KEY_elsif: - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); OPERATOR(ELSIF); case KEY_eq: @@ -3973,9 +4047,9 @@ Perl_yylex(pTHX) case KEY_for: case KEY_foreach: - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); s = skipspace(s); - if (PL_expect == XSTATE && isIDFIRST_lazy(s)) { + if (PL_expect == XSTATE && isIDFIRST_lazy_if(s,UTF)) { char *p = s; if ((PL_bufend - p) >= 3 && strnEQ(p, "my", 2) && isSPACE(*(p + 2))) @@ -3984,7 +4058,7 @@ Perl_yylex(pTHX) strnEQ(p, "our", 3) && isSPACE(*(p + 3))) p += 3; p = skipspace(p); - if (isIDFIRST_lazy(p)) { + if (isIDFIRST_lazy_if(p,UTF)) { p = scan_ident(p, PL_bufend, PL_tokenbuf, sizeof PL_tokenbuf, TRUE); p = skipspace(p); @@ -4016,7 +4090,7 @@ Perl_yylex(pTHX) Rop(OP_SGE); case KEY_grep: - LOP(OP_GREPSTART, *s == '(' ? XTERM : XREF); + LOP(OP_GREPSTART, XREF); case KEY_goto: s = force_word(s,WORD,TRUE,FALSE,FALSE); @@ -4111,7 +4185,7 @@ Perl_yylex(pTHX) UNI(OP_HEX); case KEY_if: - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); OPERATOR(IF); case KEY_index: @@ -4178,7 +4252,7 @@ Perl_yylex(pTHX) TERM(sublex_start()); case KEY_map: - LOP(OP_MAPSTART, *s == '(' ? XTERM : XREF); + LOP(OP_MAPSTART, XREF); case KEY_mkdir: LOP(OP_MKDIR,XTERM); @@ -4199,7 +4273,7 @@ Perl_yylex(pTHX) case KEY_my: PL_in_my = tmp; s = skipspace(s); - if (isIDFIRST_lazy(s)) { + if (isIDFIRST_lazy_if(s,UTF)) { s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, TRUE, &len); if (len == 3 && strnEQ(PL_tokenbuf, "sub", 3)) goto really_sub; @@ -4230,13 +4304,16 @@ Perl_yylex(pTHX) OPERATOR(USE); case KEY_not: - OPERATOR(NOTOP); + if (*s == '(' || (s = skipspace(s), *s == '(')) + FUN1(OP_NOT); + else + OPERATOR(NOTOP); case KEY_open: s = skipspace(s); - if (isIDFIRST_lazy(s)) { + if (isIDFIRST_lazy_if(s,UTF)) { char *t; - for (d = s; isALNUM_lazy(d); d++) ; + for (d = s; isALNUM_lazy_if(d,UTF); d++) ; t = skipspace(d); if (strchr("|&*+-=!?:.", *t) && ckWARN_d(WARN_AMBIGUOUS)) Perl_warner(aTHX_ WARN_AMBIGUOUS, @@ -4368,12 +4445,18 @@ Perl_yylex(pTHX) OLDLOP(OP_RETURN); case KEY_require: - *PL_tokenbuf = '\0'; - s = force_word(s,WORD,TRUE,TRUE,FALSE); - if (isIDFIRST_lazy(PL_tokenbuf)) - gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE); - else if (*s == '<') - yyerror("<> should be quotes"); + s = skipspace(s); + if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) { + s = force_version(s); + } + else { + *PL_tokenbuf = '\0'; + s = force_word(s,WORD,TRUE,TRUE,FALSE); + if (isIDFIRST_lazy_if(PL_tokenbuf,UTF)) + gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE); + else if (*s == '<') + yyerror("<> should be quotes"); + } UNI(OP_REQUIRE); case KEY_reset: @@ -4543,7 +4626,6 @@ Perl_yylex(pTHX) UNI(OP_STAT); case KEY_study: - PL_sawstudy++; UNI(OP_STUDY); case KEY_substr: @@ -4561,7 +4643,7 @@ Perl_yylex(pTHX) s = skipspace(s); - if (isIDFIRST_lazy(s) || *s == '\'' || + if (isIDFIRST_lazy_if(s,UTF) || *s == '\'' || (*s == ':' && s[1] == ':')) { PL_expect = XBLOCK; @@ -4701,11 +4783,11 @@ Perl_yylex(pTHX) UNI(OP_UNTIE); case KEY_until: - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); OPERATOR(UNTIL); case KEY_unless: - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); OPERATOR(UNLESS); case KEY_unlink: @@ -4736,9 +4818,9 @@ Perl_yylex(pTHX) if (PL_expect != XSTATE) yyerror("\"use\" not allowed in expression"); s = skipspace(s); - if(isDIGIT(*s)) { + if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) { s = force_version(s); - if(*s == ';' || (s = skipspace(s), *s == ';')) { + if (*s == ';' || (s = skipspace(s), *s == ';')) { PL_nextval[PL_nexttoke].opval = Nullop; force_next(WORD); } @@ -4754,11 +4836,10 @@ Perl_yylex(pTHX) UNI(OP_VALUES); case KEY_vec: - PL_sawvec = TRUE; LOP(OP_VEC,XTERM); case KEY_while: - yylval.ival = PL_curcop->cop_line; + yylval.ival = CopLINE(PL_curcop); OPERATOR(WHILE); case KEY_warn: @@ -4846,6 +4927,7 @@ Perl_keyword(pTHX_ register char *d, I32 len) break; case 'C': if (strEQ(d,"CORE")) return -KEY_CORE; + if (strEQ(d,"CHECK")) return KEY_CHECK; break; case 'c': switch (len) { @@ -5441,7 +5523,8 @@ S_checkcomma(pTHX_ register char *s, char *name, char *what) if (*w) for (; *w && isSPACE(*w); w++) ; if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */ - Perl_warner(aTHX_ WARN_SYNTAX, "%s (...) interpreted as function",name); + Perl_warner(aTHX_ WARN_SYNTAX, + "%s (...) interpreted as function",name); } } while (s < PL_bufend && isSPACE(*s)) @@ -5450,9 +5533,9 @@ S_checkcomma(pTHX_ register char *s, char *name, char *what) s++; while (s < PL_bufend && isSPACE(*s)) s++; - if (isIDFIRST_lazy(s)) { + if (isIDFIRST_lazy_if(s,UTF)) { w = s++; - while (isALNUM_lazy(s)) + while (isALNUM_lazy_if(s,UTF)) s++; while (s < PL_bufend && isSPACE(*s)) s++; @@ -5474,14 +5557,15 @@ S_checkcomma(pTHX_ register char *s, char *name, char *what) and type is used with error messages only. */ STATIC SV * -S_new_constant(pTHX_ char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) +S_new_constant(pTHX_ char *s, STRLEN len, const char *key, SV *sv, SV *pv, + const char *type) { dSP; HV *table = GvHV(PL_hintgv); /* ^H */ SV *res; SV **cvp; SV *cv, *typesv; - char *why, *why1, *why2; + const char *why, *why1, *why2; if (!(PL_hints & HINT_LOCALIZE_HH)) { SV *msg; @@ -5539,12 +5623,12 @@ S_new_constant(pTHX_ char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) STRLEN n_a; sv_catpv(ERRSV, "Propagated"); yyerror(SvPV(ERRSV, n_a)); /* Duplicates the message inside eval */ - POPs ; + (void)POPs; res = SvREFCNT_inc(sv); } else { res = POPs; - SvREFCNT_inc(res); + (void)SvREFCNT_inc(res); } PUTBACK ; @@ -5573,7 +5657,7 @@ S_scan_word(pTHX_ register char *s, char *dest, STRLEN destlen, int allow_packag Perl_croak(aTHX_ ident_too_long); if (isALNUM(*s)) /* UTF handled below */ *d++ = *s++; - else if (*s == '\'' && allow_package && isIDFIRST_lazy(s+1)) { + else if (*s == '\'' && allow_package && isIDFIRST_lazy_if(s+1,UTF)) { *d++ = ':'; *d++ = ':'; s++; @@ -5608,8 +5692,6 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des char *bracket = 0; char funny = *s++; - if (PL_lex_brackets == 0) - PL_lex_fakebrack = 0; if (isSPACE(*s)) s = skipspace(s); d = dest; @@ -5627,7 +5709,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des Perl_croak(aTHX_ ident_too_long); if (isALNUM(*s)) /* UTF handled below */ *d++ = *s++; - else if (*s == '\'' && isIDFIRST_lazy(s+1)) { + else if (*s == '\'' && isIDFIRST_lazy_if(s+1,UTF)) { *d++ = ':'; *d++ = ':'; s++; @@ -5658,7 +5740,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des return s; } if (*s == '$' && s[1] && - (isALNUM_lazy(s+1) || strchr("${", s[1]) || strnEQ(s+1,"::",2)) ) + (isALNUM_lazy_if(s+1,UTF) || strchr("${", s[1]) || strnEQ(s+1,"::",2)) ) { return s; } @@ -5685,11 +5767,11 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des } } } - if (isIDFIRST_lazy(d)) { + if (isIDFIRST_lazy_if(d,UTF)) { d++; if (UTF) { e = s; - while (e < send && isALNUM_lazy(e) || *e == ':') { + while (e < send && isALNUM_lazy_if(e,UTF) || *e == ':') { e += UTF8SKIP(e); while (e < send && *e & 0x80 && is_utf8_mark((U8*)e)) e += UTF8SKIP(e); @@ -5709,14 +5791,13 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) { dTHR; /* only for ckWARN */ if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) { - char *brack = *s == '[' ? "[...]" : "{...}"; + const char *brack = *s == '[' ? "[...]" : "{...}"; Perl_warner(aTHX_ WARN_AMBIGUOUS, "Ambiguous use of %c{%s%s} resolved to %c%s%s", funny, dest, brack, funny, dest, brack); } - PL_lex_fakebrack = PL_lex_brackets+1; bracket++; - PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR; + PL_lex_brackstack[PL_lex_brackets++] = (char)(XOPERATOR | XFAKEBRACK); return s; } } @@ -5994,9 +6075,9 @@ S_scan_heredoc(pTHX_ register char *s) s++, term = '\''; else term = '"'; - if (!isALNUM_lazy(s)) + if (!isALNUM_lazy_if(s,UTF)) deprecate("bare << to mean <<\"\""); - for (; isALNUM_lazy(s); s++) { + for (; isALNUM_lazy_if(s,UTF); s++) { if (d < e) *d++ = *s; } @@ -6049,7 +6130,7 @@ S_scan_heredoc(pTHX_ register char *s) } CLINE; - PL_multi_start = PL_curcop->cop_line; + PL_multi_start = CopLINE(PL_curcop); PL_multi_open = PL_multi_close = '<'; term = *PL_tokenbuf; if (PL_lex_inwhat == OP_SUBST && PL_in_eval && !PL_rsfp) { @@ -6063,10 +6144,10 @@ S_scan_heredoc(pTHX_ register char *s) while (s < bufend && (*s != term || memNE(s,PL_tokenbuf,len)) ) { if (*s++ == '\n') - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); } if (s >= bufend) { - PL_curcop->cop_line = PL_multi_start; + CopLINE_set(PL_curcop, PL_multi_start); missingterm(PL_tokenbuf); } sv_setpvn(herewas,bufptr,d-bufptr+1); @@ -6083,15 +6164,15 @@ S_scan_heredoc(pTHX_ register char *s) while (s < PL_bufend && (*s != term || memNE(s,PL_tokenbuf,len)) ) { if (*s++ == '\n') - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); } if (s >= PL_bufend) { - PL_curcop->cop_line = PL_multi_start; + CopLINE_set(PL_curcop, PL_multi_start); missingterm(PL_tokenbuf); } sv_setpvn(tmpstr,d+1,s-d); s += len - 1; - PL_curcop->cop_line++; /* the preceding stmt passes a newline */ + CopLINE_inc(PL_curcop); /* the preceding stmt passes a newline */ sv_catpvn(herewas,s,PL_bufend-s); sv_setsv(PL_linestr,herewas); @@ -6103,10 +6184,10 @@ S_scan_heredoc(pTHX_ register char *s) while (s >= PL_bufend) { /* multiple line string? */ if (!outer || !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) { - PL_curcop->cop_line = PL_multi_start; + CopLINE_set(PL_curcop, PL_multi_start); missingterm(PL_tokenbuf); } - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); #ifndef PERL_STRICT_CR if (PL_bufend - PL_linestart >= 2) { @@ -6128,8 +6209,7 @@ S_scan_heredoc(pTHX_ register char *s) sv_upgrade(sv, SVt_PVMG); sv_setsv(sv,PL_linestr); - av_store(GvAV(PL_curcop->cop_filegv), - (I32)PL_curcop->cop_line,sv); + av_store(CopFILEAV(PL_curcop), (I32)CopLINE(PL_curcop),sv); } if (*s == term && memEQ(s,PL_tokenbuf,len)) { s = PL_bufend - 1; @@ -6144,7 +6224,7 @@ S_scan_heredoc(pTHX_ register char *s) } s++; retval: - PL_multi_end = PL_curcop->cop_line; + PL_multi_end = CopLINE(PL_curcop); if (SvCUR(tmpstr) + 5 < SvLEN(tmpstr)) { SvLEN_set(tmpstr, SvCUR(tmpstr) + 1); Renew(SvPVX(tmpstr), SvLEN(tmpstr), char); @@ -6208,7 +6288,7 @@ S_scan_inputsymbol(pTHX_ char *start) if (*d == '$' && d[1]) d++; /* allow or */ - while (*d && (isALNUM_lazy(d) || *d == '\'' || *d == ':')) + while (*d && (isALNUM_lazy_if(d,UTF) || *d == '\'' || *d == ':')) d++; /* If we've tried to read what we allow filehandles to look like, and @@ -6324,6 +6404,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) register char term; /* terminating character */ register char *to; /* current position in the sv's data */ I32 brackets = 1; /* bracket nesting level */ + bool has_utf = FALSE; /* is there any utf8 content? */ /* skip space before the delimiter */ if (isSPACE(*s)) @@ -6334,8 +6415,11 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) /* after skipping whitespace, the next character is the terminator */ term = *s; + if ((term & 0x80) && UTF) + has_utf = TRUE; + /* mark where we are */ - PL_multi_start = PL_curcop->cop_line; + PL_multi_start = CopLINE(PL_curcop); PL_multi_open = term; /* find corresponding closing delimiter */ @@ -6365,7 +6449,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) for (; s < PL_bufend; s++,to++) { /* embedded newlines increment the current line number */ if (*s == '\n' && !PL_rsfp) - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); /* handle quoted delimiters */ if (*s == '\\' && s+1 < PL_bufend && term != '\\') { if (!keep_quoted && s[1] == term) @@ -6378,6 +6462,8 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) have found the terminator */ else if (*s == term) break; + else if (!has_utf && (*s & 0x80) && UTF) + has_utf = TRUE; *to = *s; } } @@ -6391,7 +6477,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) for (; s < PL_bufend; s++,to++) { /* embedded newlines increment the line count */ if (*s == '\n' && !PL_rsfp) - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); /* backslashes can escape the open or closing characters */ if (*s == '\\' && s+1 < PL_bufend) { if (!keep_quoted && @@ -6405,6 +6491,8 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) break; else if (*s == PL_multi_open) brackets++; + else if (!has_utf && (*s & 0x80) && UTF) + has_utf = TRUE; *to = *s; } } @@ -6416,7 +6504,8 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) * this next chunk reads more into the buffer if we're not done yet */ - if (s < PL_bufend) break; /* handle case where we are done yet :-) */ + if (s < PL_bufend) + break; /* handle case where we are done yet :-) */ #ifndef PERL_STRICT_CR if (to - SvPVX(sv) >= 2) { @@ -6440,11 +6529,11 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) if (!PL_rsfp || !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) { sv_free(sv); - PL_curcop->cop_line = PL_multi_start; + CopLINE_set(PL_curcop, PL_multi_start); return Nullch; } /* we read a line, so increment our line counter */ - PL_curcop->cop_line++; + CopLINE_inc(PL_curcop); /* update debugger info */ if (PERLDB_LINE && PL_curstash != PL_debstash) { @@ -6452,8 +6541,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) sv_upgrade(sv, SVt_PVMG); sv_setsv(sv,PL_linestr); - av_store(GvAV(PL_curcop->cop_filegv), - (I32)PL_curcop->cop_line, sv); + av_store(CopFILEAV(PL_curcop), (I32)CopLINE(PL_curcop), sv); } /* having changed the buffer, we must update PL_bufend */ @@ -6464,7 +6552,9 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims) if (keep_delims) sv_catpvn(sv, s, 1); - PL_multi_end = PL_curcop->cop_line; + if (has_utf) + SvUTF8_on(sv); + PL_multi_end = CopLINE(PL_curcop); s++; /* if we allocated too much space, give some back */ @@ -6514,7 +6604,7 @@ Perl_scan_num(pTHX_ char *start) register char *e; /* end of temp buffer */ IV tryiv; /* used to see if it can be an IV */ NV value; /* number read, as a double */ - SV *sv; /* place to put the converted number */ + SV *sv = Nullsv; /* place to put the converted number */ bool floatit; /* boolean: int or float? */ char *lastub = 0; /* position of last underbar */ static char number_too_long[] = "Number too long"; @@ -6526,8 +6616,7 @@ Perl_scan_num(pTHX_ char *start) Perl_croak(aTHX_ "panic: scan_num"); /* if it starts with a 0, it could be an octal number, a decimal in - 0.13 disguise, or a hexadecimal number, or a binary number. - */ + 0.13 disguise, or a hexadecimal number, or a binary number. */ case '0': { /* variables: @@ -6789,11 +6878,75 @@ Perl_scan_num(pTHX_ char *start) (floatit ? "float" : "integer"), sv, Nullsv, NULL); break; + /* if it starts with a v, it could be a version number */ + case 'v': + { + char *pos = s; + pos++; + while (isDIGIT(*pos)) + pos++; + if (*pos == '.' && isDIGIT(pos[1])) { + UV rev; + U8 tmpbuf[10]; + U8 *tmpend; + NV nshift = 1.0; + bool utf8 = FALSE; + s++; /* get past 'v' */ + + sv = NEWSV(92,5); + SvUPGRADE(sv, SVt_PVNV); + sv_setpvn(sv, "", 0); + + do { + if (*s == '0' && isDIGIT(s[1])) + yyerror("Octal number in vector unsupported"); + rev = atoi(s); + s = ++pos; + while (isDIGIT(*pos)) + pos++; + + if (rev > 127) { + tmpend = uv_to_utf8(tmpbuf, rev); + utf8 = TRUE; + } + else { + tmpbuf[0] = (U8)rev; + tmpend = &tmpbuf[1]; + } + *tmpend = '\0'; + sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf); + if (rev > 0) + SvNVX(sv) += (NV)rev/nshift; + nshift *= 1000; + } while (*pos == '.' && isDIGIT(pos[1])); + + if (*s == '0' && isDIGIT(s[1])) + yyerror("Octal number in vector unsupported"); + rev = atoi(s); + s = pos; + tmpend = uv_to_utf8(tmpbuf, rev); + utf8 = utf8 || rev > 127; + *tmpend = '\0'; + sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf); + if (rev > 0) + SvNVX(sv) += (NV)rev/nshift; + + SvPOK_on(sv); + SvNOK_on(sv); + SvREADONLY_on(sv); + if (utf8) + SvUTF8_on(sv); + } + } + break; } /* make the op for the constant and return */ - yylval.opval = newSVOP(OP_CONST, 0, sv); + if (sv) + yylval.opval = newSVOP(OP_CONST, 0, sv); + else + yylval.opval = Nullop; return s; } @@ -6835,6 +6988,14 @@ S_scan_formline(pTHX_ register char *s) needargs = TRUE; } sv_catpvn(stuff, s, eol-s); +#ifndef PERL_STRICT_CR + if (eol-s > 1 && eol[-2] == '\r' && eol[-1] == '\n') { + char *end = SvPVX(stuff) + SvCUR(stuff); + end[-2] = '\n'; + end[-1] = '\0'; + SvCUR(stuff)--; + } +#endif } s = eol; if (PL_rsfp) { @@ -6892,11 +7053,10 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags) if (PL_compcv) { assert(SvTYPE(PL_compcv) == SVt_PVCV); } - save_I32(&PL_subline); + SAVEI32(PL_subline); save_item(PL_subname); SAVEI32(PL_padix); - SAVESPTR(PL_curpad); - SAVESPTR(PL_comppad); + SAVECOMPPAD(); SAVESPTR(PL_comppad_name); SAVESPTR(PL_compcv); SAVEI32(PL_comppad_name_fill); @@ -6915,7 +7075,7 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags) PL_comppad_name_fill = 0; PL_min_intro_pending = 0; PL_padix = 0; - PL_subline = PL_curcop->cop_line; + PL_subline = CopLINE(PL_curcop); #ifdef USE_THREADS av_store(PL_comppad_name, 0, newSVpvn("@_", 2)); PL_curpad[0] = (SV*)newAV(); @@ -6995,36 +7155,24 @@ Perl_yyerror(pTHX_ char *s) where = SvPVX(where_sv); } msg = sv_2mortal(newSVpv(s, 0)); -#ifdef IV_IS_QUAD - Perl_sv_catpvf(aTHX_ msg, " at %_ line %" PERL_PRId64 ", ", - GvSV(PL_curcop->cop_filegv), (IV)PL_curcop->cop_line); -#else - Perl_sv_catpvf(aTHX_ msg, " at %_ line %ld, ", - GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line); -#endif + Perl_sv_catpvf(aTHX_ msg, " at %s line %"IVdf", ", + CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); if (context) Perl_sv_catpvf(aTHX_ msg, "near \"%.*s\"\n", contlen, context); else Perl_sv_catpvf(aTHX_ msg, "%s\n", where); - if (PL_multi_start < PL_multi_end && (U32)(PL_curcop->cop_line - PL_multi_end) <= 1) { -#ifdef IV_IS_QUAD + if (PL_multi_start < PL_multi_end && (U32)(CopLINE(PL_curcop) - PL_multi_end) <= 1) { Perl_sv_catpvf(aTHX_ msg, - " (Might be a runaway multi-line %c%c string starting on line %" PERL_\ -PRId64 ")\n", + " (Might be a runaway multi-line %c%c string starting on line %"IVdf")\n", (int)PL_multi_open,(int)PL_multi_close,(IV)PL_multi_start); -#else - Perl_sv_catpvf(aTHX_ msg, - " (Might be a runaway multi-line %c%c string starting on line %ld)\n", - (int)PL_multi_open,(int)PL_multi_close,(long)PL_multi_start); -#endif PL_multi_end = 0; } if (PL_in_eval & EVAL_WARNONLY) - Perl_warn(aTHX_ "%_", msg); + Perl_warn(aTHX_ "%"SVf, msg); else qerror(msg); if (PL_error_count >= 10) - Perl_croak(aTHX_ "%_ has too many errors.\n", GvSV(PL_curcop->cop_filegv)); + Perl_croak(aTHX_ "%s has too many errors.\n", CopFILE(PL_curcop)); PL_in_my = 0; PL_in_my_stash = Nullhv; return 0; @@ -7032,7 +7180,6 @@ PRId64 ")\n", #ifdef PERL_OBJECT -#define NO_XSLOCKS #include "XSUB.h" #endif @@ -7052,29 +7199,3 @@ restore_rsfp(pTHXo_ void *f) PerlIO_close(PL_rsfp); PL_rsfp = fp; } - -/* - * restore_expect - * Restores the state of PL_expect when the lexing that begun with a - * start_lex() call has ended. - */ - -static void -restore_expect(pTHXo_ void *e) -{ - /* a safe way to store a small integer in a pointer */ - PL_expect = (expectation)((char *)e - PL_tokenbuf); -} - -/* - * restore_lex_expect - * Restores the state of PL_lex_expect when the lexing that begun with a - * start_lex() call has ended. - */ - -static void -restore_lex_expect(pTHXo_ void *e) -{ - /* a safe way to store a small integer in a pointer */ - PL_lex_expect = (expectation)((char *)e - PL_tokenbuf); -}