X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=toke.c;h=e7e217473ea0b19e09cbc6043f968a19e4d878af;hb=030866aa8d0911636ef2210b710f544fd2c85c8e;hp=8eac820baa38c332b026f235edafd7c66b16aea3;hpb=d0456cad3918fc93900d9454be6ff427d745b536;p=p5sagit%2Fp5-mst-13.2.git diff --git a/toke.c b/toke.c index 8eac820..e7e2174 100644 --- a/toke.c +++ b/toke.c @@ -28,8 +28,9 @@ 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 (PL_hints & HINT_UTF8) /* @@ -303,15 +304,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,7 +382,6 @@ 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); @@ -380,14 +401,13 @@ Perl_lex_start(pTHX_ SV *line) SAVEI32(PL_lex_defer); SAVEI32(PL_sublex_info.sub_inwhat); SAVESPTR(PL_lex_repl); - SAVEDESTRUCTOR_X(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */ - SAVEDESTRUCTOR_X(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); @@ -475,8 +495,6 @@ S_incline(pTHX_ char *s) *t = '\0'; if (t - s > 0) CopFILE_set(PL_curcop, s); - else - CopFILE_set(PL_curcop, PL_origfilename); *t = ch; CopLINE_set(PL_curcop, atoi(n)-1); } @@ -673,7 +691,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; @@ -804,13 +822,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,7 +980,6 @@ 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); @@ -988,7 +1004,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); @@ -1036,7 +1051,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; @@ -1368,7 +1382,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; } @@ -1877,9 +1891,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) { @@ -1962,6 +1976,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 { @@ -1999,15 +2017,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 @@ -2729,6 +2751,21 @@ Perl_yylex(pTHX) attrs = Nullop; while (isIDFIRST_lazy(s)) { 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) { @@ -2760,11 +2797,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) { @@ -2784,6 +2823,7 @@ Perl_yylex(pTHX) op_free(attrs); OPERATOR(':'); } + got_attrs: if (attrs) { PL_nextval[PL_nexttoke].opval = attrs; force_next(THING); @@ -2913,7 +2953,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; @@ -2944,8 +2985,10 @@ Perl_yylex(pTHX) } t++; } - else if (isIDFIRST_lazy(s)) { - for (t++; t < PL_bufend && isALNUM_lazy(t); t++) ; + else if (isALNUM_lazy(t)) { + t += UTF8SKIP(t); + while (t < PL_bufend && isALNUM_lazy(t)) + t += UTF8SKIP(t); } while (t < PL_bufend && isSPACE(*t)) t++; @@ -2978,7 +3021,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 */ @@ -2989,9 +3033,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('}'); @@ -3399,6 +3443,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++; @@ -3428,7 +3485,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': @@ -3773,6 +3830,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; @@ -3781,9 +3860,9 @@ Perl_yylex(pTHX) case KEY_AUTOLOAD: case KEY_DESTROY: case KEY_BEGIN: - case KEY_END: - case KEY_STOP: + case KEY_CHECK: case KEY_INIT: + case KEY_END: if (PL_expect == XSTATE) { s = PL_bufptr; goto really_sub; @@ -4007,7 +4086,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); @@ -4169,7 +4248,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); @@ -4362,12 +4441,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(PL_tokenbuf)) + gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE); + else if (*s == '<') + yyerror("<> should be quotes"); + } UNI(OP_REQUIRE); case KEY_reset: @@ -4729,9 +4814,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); } @@ -4838,6 +4923,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) { @@ -5221,9 +5307,6 @@ Perl_keyword(pTHX_ register char *d, I32 len) break; } break; - case 'S': - if (strEQ(d,"STOP")) return KEY_STOP; - break; case 's': switch (d[1]) { case 0: return KEY_s; @@ -5605,8 +5688,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; @@ -5711,9 +5792,8 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des "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; } } @@ -6509,7 +6589,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"; @@ -6521,8 +6601,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: @@ -6784,11 +6863,61 @@ 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; + s++; /* get past 'v' */ + + sv = NEWSV(92,5); + SvUPGRADE(sv, SVt_PVNV); + sv_setpvn(sv, "", 0); + + do { + rev = atoi(s); + s = ++pos; + while (isDIGIT(*pos)) + pos++; + + tmpend = uv_to_utf8(tmpbuf, rev); + *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])); + + rev = atoi(s); + s = pos; + tmpend = uv_to_utf8(tmpbuf, rev); + *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); + 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; } @@ -6830,6 +6959,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) { @@ -7003,7 +7140,7 @@ Perl_yyerror(pTHX_ char *s) 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) @@ -7034,29 +7171,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); -}