X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=toke.c;h=709db636d1986ed5edcd125834c6e3213780330b;hb=7509b6572737d9774c4d9688c4edf46238aa95f2;hp=9475b25fcf08bf4c69bfdb7cdee8b9f05b0bd704;hpb=b8957cf14d64aac7919c660fa810962ddf2b2dee;p=p5sagit%2Fp5-mst-13.2.git diff --git a/toke.c b/toke.c index 9475b25..709db63 100644 --- a/toke.c +++ b/toke.c @@ -1,6 +1,6 @@ /* toke.c * - * Copyright (c) 1991-1997, Larry Wall + * Copyright (c) 1991-1999, 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. @@ -14,6 +14,9 @@ #include "EXTERN.h" #include "perl.h" +#define yychar PL_yychar +#define yylval PL_yylval + #ifndef PERL_OBJECT static void check_uni _((void)); static void force_next _((I32 type)); @@ -57,6 +60,24 @@ static void restore_lex_expect _((void *e)); static char ident_too_long[] = "Identifier too long"; +#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 */ +#define isCONTROLVAR(x) (isUPPER(x) || strchr("[\\]^_?", (x))) + /* The following are arranged oddly so that the guard on the switch statement * can get by with a single comparison (if the compiler is smart enough). */ @@ -92,6 +113,18 @@ static char ident_too_long[] = "Identifier too long"; #undef ff_next #endif +#ifdef USE_PURE_BISON +YYSTYPE* yylval_pointer = NULL; +int* yychar_pointer = NULL; +# undef yylval +# undef yychar +# define yylval (*yylval_pointer) +# define yychar (*yychar_pointer) +# define PERL_YYLEX_PARAM yylval_pointer,yychar_pointer +#else +# define PERL_YYLEX_PARAM +#endif + #include "keywords.h" #ifdef CLINE @@ -162,14 +195,16 @@ no_op(char *what, char *s) yywarn(form("%s found where operator expected", what)); if (is_first) warn("\t(Missing semicolon on previous line?)\n"); - else if (PL_oldoldbufptr && isIDFIRST(*PL_oldoldbufptr)) { + else if (PL_oldoldbufptr && isIDFIRST_lazy(PL_oldoldbufptr)) { char *t; - for (t = PL_oldoldbufptr; *t && (isALNUM(*t) || *t == ':'); t++) ; + for (t = PL_oldoldbufptr; *t && (isALNUM_lazy(t) || *t == ':'); t++) ; if (t < PL_bufptr && isSPACE(*t)) warn("\t(Do you need to predeclare %.*s?)\n", t - PL_oldoldbufptr, PL_oldoldbufptr); } + else if (s <= oldbp) + warn("\t(Missing operator before end of line?)\n"); else warn("\t(Missing operator before %.*s?)\n", s - oldbp, oldbp); PL_bufptr = oldbp; @@ -185,7 +220,13 @@ missingterm(char *s) if (nl) *nl = '\0'; } - else if (PL_multi_close < 32 || PL_multi_close == 127) { + else if ( +#ifdef EBCDIC + iscntrl(PL_multi_close) +#else + PL_multi_close < 32 || PL_multi_close == 127 +#endif + ) { *tmpbuf = '^'; tmpbuf[1] = toCTRL(PL_multi_close); s = "\\n"; @@ -204,8 +245,9 @@ missingterm(char *s) void deprecate(char *s) { - if (PL_dowarn) - warn("Use of %s is deprecated", s); + dTHR; + if (ckWARN(WARN_DEPRECATED)) + warner(WARN_DEPRECATED, "Use of %s is deprecated", s); } STATIC void @@ -226,6 +268,39 @@ win32_textfilter(int idx, SV *sv, int maxlen) } #endif +#ifndef PERL_OBJECT + +STATIC I32 +utf16_textfilter(int idx, SV *sv, int maxlen) +{ + I32 count = FILTER_READ(idx+1, sv, maxlen); + if (count) { + U8* tmps; + U8* tend; + New(898, tmps, SvCUR(sv) * 3 / 2 + 1, U8); + tend = utf16_to_utf8((U16*)SvPVX(sv), tmps, SvCUR(sv)); + sv_usepvn(sv, (char*)tmps, tend - tmps); + + } + return count; +} + +STATIC I32 +utf16rev_textfilter(int idx, SV *sv, int maxlen) +{ + I32 count = FILTER_READ(idx+1, sv, maxlen); + if (count) { + U8* tmps; + U8* tend; + New(898, tmps, SvCUR(sv) * 3 / 2 + 1, U8); + tend = utf16_to_utf8_reversed((U16*)SvPVX(sv), tmps, SvCUR(sv)); + sv_usepvn(sv, (char*)tmps, tend - tmps); + + } + return count; +} + +#endif void lex_start(SV *line) @@ -288,7 +363,7 @@ lex_start(SV *line) PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = SvPVX(PL_linestr); PL_bufend = PL_bufptr + SvCUR(PL_linestr); SvREFCNT_dec(PL_rs); - PL_rs = newSVpv("\n", 1); + PL_rs = newSVpvn("\n", 1); PL_rsfp = 0; } @@ -376,13 +451,20 @@ skipspace(register char *s) } for (;;) { STRLEN prevlen; - while (s < PL_bufend && isSPACE(*s)) - s++; + while (s < PL_bufend && isSPACE(*s)) { + if (*s++ == '\n' && PL_in_eval && !PL_rsfp) + incline(s); + } if (s < PL_bufend && *s == '#') { while (s < PL_bufend && *s != '\n') s++; - if (s < PL_bufend) + if (s < PL_bufend) { s++; + if (PL_in_eval && !PL_rsfp) { + incline(s); + continue; + } + } } if (s < PL_bufend || !PL_rsfp || PL_lex_state != LEX_NORMAL) return s; @@ -431,7 +513,7 @@ check_uni(void) { return; while (isSPACE(*PL_last_uni)) PL_last_uni++; - for (s = PL_last_uni; isALNUM(*s) || *s == '-'; s++) ; + for (s = PL_last_uni; isALNUM_lazy(s) || *s == '-'; s++) ; if ((t = strchr(s, '(')) && t < PL_bufptr) return; ch = *s; @@ -507,7 +589,7 @@ force_word(register char *start, int token, int check_keyword, int allow_pack, i start = skipspace(start); s = start; - if (isIDFIRST(*s) || + if (isIDFIRST_lazy(s) || (allow_pack && *s == ':') || (allow_initial_tick && *s == '\'') ) { @@ -520,8 +602,6 @@ force_word(register char *start, int token, int check_keyword, int allow_pack, i PL_expect = XTERM; else { PL_expect = XOPERATOR; - force_next(')'); - force_next('('); } } PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST,0, newSVpv(PL_tokenbuf,0)); @@ -603,7 +683,7 @@ tokeq(SV *sv) goto finish; d = s; if ( PL_hints & HINT_NEW_STRING ) - pv = sv_2mortal(newSVpv(SvPVX(pv), len)); + pv = sv_2mortal(newSVpvn(SvPVX(pv), len)); while (s < send) { if (*s == '\\') { if (s + 1 < send && (s[1] == '\\')) @@ -639,7 +719,7 @@ sublex_start(void) SV *nsv; p = SvPV(sv, len); - nsv = newSVpv(p, len); + nsv = newSVpvn(p, len); SvREFCNT_dec(sv); sv = nsv; } @@ -721,13 +801,13 @@ sublex_done(void) { if (!PL_lex_starts++) { PL_expect = XOPERATOR; - yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv("",0)); + yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpvn("",0)); return THING; } if (PL_lex_casemods) { /* oops, we've got some unbalanced parens */ PL_lex_state = LEX_INTERPCASEMOD; - return yylex(); + return yylex(PERL_YYLEX_PARAM); } /* Is there a right-hand side to take care of? */ @@ -746,10 +826,15 @@ sublex_done(void) if (SvCOMPILED(PL_lex_repl)) { PL_lex_state = LEX_INTERPNORMAL; PL_lex_starts++; + /* we don't clear PL_lex_repl here, so that we can check later + whether this is an evalled subst; that means we rely on the + logic to ensure sublex_done() is called again only via the + branch (in yylex()) that clears PL_lex_repl, else we'll loop */ } - else + else { PL_lex_state = LEX_INTERPCONCAT; - PL_lex_repl = Nullsv; + PL_lex_repl = Nullsv; + } return ','; } else { @@ -843,11 +928,17 @@ scan_const(char *start) register char *d = SvPVX(sv); /* destination for copies */ bool dorange = FALSE; /* are we in a translit range? */ 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)) + : UTF; + I32 thisutf = (PL_lex_inwhat == OP_TRANS && PL_sublex_info.sub_op) + ? (PL_sublex_info.sub_op->op_private & (PL_lex_repl ? OPpTRANS_FROM_UTF : OPpTRANS_TO_UTF)) + : UTF; /* leaveit is the set of acceptably-backslashed characters */ char *leaveit = PL_lex_inpat - ? "\\.^$@AGZdDwWsSbB+*?|()-nrtfeaxcz0123456789[{]} \t\n\r\f\v#" + ? "\\.^$@AGZdDwWsSbBpPXC+*?|()-nrtfeaxcz0123456789[{]} \t\n\r\f\v#" : ""; while (s < send || dorange) { @@ -856,6 +947,7 @@ scan_const(char *start) /* expand a range A-Z to the full set of characters. AIE! */ if (dorange) { I32 i; /* current expanded character */ + I32 min; /* first character in range */ I32 max; /* last character in range */ i = d - SvPVX(sv); /* remember current offset */ @@ -863,10 +955,26 @@ scan_const(char *start) d = SvPVX(sv) + i; /* restore d after the grow potentially has changed the ptr */ d -= 2; /* eat the first char and the - */ - max = (U8)d[1]; /* last char in range */ - - for (i = (U8)*d; i <= max; i++) - *d++ = i; + min = (U8)*d; /* first char in range */ + max = (U8)d[1]; /* last char in range */ + +#ifndef ASCIIish + if ((isLOWER(min) && isLOWER(max)) || + (isUPPER(min) && isUPPER(max))) { + if (isLOWER(min)) { + for (i = min; i <= max; i++) + if (isLOWER(i)) + *d++ = i; + } else { + for (i = min; i <= max; i++) + if (isUPPER(i)) + *d++ = i; + } + } + else +#endif + for (i = min; i <= max; i++) + *d++ = i; /* mark the range as done, and continue */ dorange = FALSE; @@ -875,6 +983,11 @@ scan_const(char *start) /* range begins (ignore - as first or last char) */ else if (*s == '-' && s+1 < send && s != start) { + if (utf) { + *d++ = (char)0xff; /* use illegal utf8 byte--see pmtrans */ + s++; + continue; + } dorange = TRUE; s++; } @@ -882,14 +995,16 @@ scan_const(char *start) /* if we get here, we're not doing a transliteration */ - /* skip for regexp comments /(?#comment)/ */ + /* skip for regexp comments /(?#comment)/ and code /(?{code})/, + except for the last char, which will be done separately. */ else if (*s == '(' && PL_lex_inpat && s[1] == '?') { if (s[2] == '#') { while (s < send && *s != ')') *d++ = *s++; - } else if (s[2] == '{') { /* This should march regcomp.c */ + } else if (s[2] == '{' + || s[2] == 'p' && s[3] == '{') { /* This should march regcomp.c */ I32 count = 1; - char *regparse = s + 3; + char *regparse = s + (s[2] == '{' ? 3 : 4); char c; while (count && (c = *regparse)) { @@ -901,11 +1016,11 @@ scan_const(char *start) count--; regparse++; } - if (*regparse == ')') - regparse++; - else + if (*regparse != ')') { + regparse--; /* Leave one char for continuation. */ yyerror("Sequence (?{...}) not terminated or not {}-balanced"); - while (s < regparse && *s != ')') + } + while (s < regparse) *d++ = *s++; } } @@ -918,7 +1033,7 @@ scan_const(char *start) } /* check for embedded arrays (@foo, @:foo, @'foo, @{foo}, @$foo) */ - else if (*s == '@' && s[1] && (isALNUM(s[1]) || strchr(":'{$", s[1]))) + else if (*s == '@' && s[1] && (isALNUM_lazy(s+1) || strchr(":'{$", s[1]))) break; /* check for embedded scalars. only stop if we're sure it's a @@ -931,12 +1046,26 @@ scan_const(char *start) break; /* in regexp, $ might be tail anchor */ } + /* (now in tr/// code again) */ + + if (*s & 0x80 && thisutf) { + dTHR; /* only for ckWARN */ + if (ckWARN(WARN_UTF8)) { + (void)utf8_to_uv((U8*)s, &len); /* could cvt latin-1 to utf8 here... */ + if (len) { + while (len--) + *d++ = *s++; + continue; + } + } + } + /* backslashes */ if (*s == '\\' && s+1 < send) { s++; /* some backslashes we leave behind */ - if (*s && strchr(leaveit, *s)) { + if (*leaveit && *s && strchr(leaveit, *s)) { *d++ = '\\'; *d++ = *s++; continue; @@ -946,8 +1075,9 @@ scan_const(char *start) if (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat && isDIGIT(*s) && *s != '0' && !isDIGIT(s[1])) { - if (PL_dowarn) - warn("\\%c better written as $%c", *s, *s); + dTHR; /* only for ckWARN */ + if (ckWARN(WARN_SYNTAX)) + warner(WARN_SYNTAX, "\\%c better written as $%c", *s, *s); *--s = '$'; break; } @@ -968,10 +1098,17 @@ scan_const(char *start) continue; } /* FALL THROUGH */ - /* default action is to copy the quoted character */ default: - *d++ = *s++; - continue; + { + dTHR; + if (ckWARN(WARN_UNSAFE) && isALPHA(*s)) + warner(WARN_UNSAFE, + "Unrecognized escape \\%c passed through", + *s); + /* default action is to copy the quoted character */ + *d++ = *s++; + continue; + } /* \132 indicates an octal constant */ case '0': case '1': case '2': case '3': @@ -982,15 +1119,59 @@ scan_const(char *start) /* \x24 indicates a hex constant */ case 'x': - *d++ = scan_hex(++s, 2, &len); - s += len; + ++s; + if (*s == '{') { + char* e = strchr(s, '}'); + + if (!e) { + yyerror("Missing right brace on \\x{}"); + e = s; + } + if (!utf) { + dTHR; + if (ckWARN(WARN_UTF8)) + warner(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)); + s = e + 1; + + } + else { + UV uv = (UV)scan_hex(s, 2, &len); + if (utf && PL_lex_inwhat == OP_TRANS && + utf != (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) + { + d = (char*)uv_to_utf8((U8*)d, uv); /* doing a CU or UC */ + } + else { + if (uv >= 127 && UTF) { + dTHR; + if (ckWARN(WARN_UTF8)) + warner(WARN_UTF8, + "\\x%.*s will produce malformed UTF-8 character; use \\x{%.*s} for that", + len,s,len,s); + } + *d++ = (char)uv; + } + s += len; + } continue; /* \c is a control character */ case 'c': s++; +#ifdef EBCDIC + *d = *s++; + if (isLOWER(*d)) + *d = toUPPER(*d); + *d++ = toCTRL(*d); +#else len = *s++; *d++ = toCTRL(len); +#endif continue; /* printf-style backslashes, formfeeds, newlines, etc */ @@ -1115,7 +1296,7 @@ intuit_more(register char *s) case '&': case '$': weight -= seen[un_char] * 10; - if (isALNUM(s[1])) { + if (isALNUM_lazy(s+1)) { scan_ident(s, send, tmpbuf, sizeof tmpbuf, FALSE); if ((int)strlen(tmpbuf) > 1 && gv_fetchpv(tmpbuf,FALSE, SVt_PV)) weight -= 100; @@ -1230,7 +1411,7 @@ intuit_method(char *start, GV *gv) return 0; /* no assumptions -- "=>" quotes bearword */ bare_package: PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, - newSVpv(tmpbuf,0)); + newSVpvn(tmpbuf,len)); PL_nextval[PL_nexttoke].opval->op_private = OPpCONST_BARE; PL_expect = XTERM; force_next(WORD); @@ -1271,13 +1452,12 @@ incl_perldb(void) * Note that IoTOP_NAME, IoFMT_NAME, IoBOTTOM_NAME, if set for * private use must be set using malloc'd pointers. */ -static int filter_debug = 0; SV * filter_add(filter_t funcp, SV *datasv) { if (!funcp){ /* temporary handy debugging hack to be deleted */ - filter_debug = atoi((char*)datasv); + PL_filter_debug = atoi((char*)datasv); return NULL; } if (!PL_rsfp_filters) @@ -1287,8 +1467,10 @@ filter_add(filter_t funcp, SV *datasv) if (!SvUPGRADE(datasv, SVt_PVIO)) die("Can't upgrade filter_add data to SVt_PVIO"); IoDIRP(datasv) = (DIR*)funcp; /* stash funcp into spare field */ - if (filter_debug) - warn("filter_add func %p (%s)", funcp, SvPV(datasv,PL_na)); + if (PL_filter_debug) { + STRLEN n_a; + warn("filter_add func %p (%s)", funcp, SvPV(datasv, n_a)); + } av_unshift(PL_rsfp_filters, 1); av_store(PL_rsfp_filters, 0, datasv) ; return(datasv); @@ -1299,12 +1481,12 @@ filter_add(filter_t funcp, SV *datasv) void filter_del(filter_t funcp) { - if (filter_debug) + if (PL_filter_debug) warn("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))) == (void*)funcp){ + if (IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) == (DIR*)funcp){ sv_free(av_pop(PL_rsfp_filters)); return; @@ -1329,7 +1511,7 @@ filter_read(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. */ - if (filter_debug) + if (PL_filter_debug) warn("filter_read %d: from rsfp\n", idx); if (maxlen) { /* Want a block */ @@ -1358,15 +1540,17 @@ filter_read(int idx, SV *buf_sv, int maxlen) } /* Skip this filter slot if filter has been deleted */ if ( (datasv = FILTER_DATA(idx)) == &PL_sv_undef){ - if (filter_debug) + if (PL_filter_debug) warn("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); - if (filter_debug) + if (PL_filter_debug) { + STRLEN n_a; warn("filter_read %d: via function %p (%s)\n", - idx, funcp, SvPV(datasv,PL_na)); + idx, funcp, SvPV(datasv,n_a)); + } /* Call function. The function is expected to */ /* call "FILTER_READ(idx+1, buf_sv)" first. */ /* Return: <0:error, =0:eof, >0:not eof */ @@ -1390,7 +1574,7 @@ filter_gets(register SV *sv, register PerlIO *fp, STRLEN append) else return Nullch ; } - else + else return (sv_gets(sv, fp, append)); } @@ -1400,8 +1584,6 @@ filter_gets(register SV *sv, register PerlIO *fp, STRLEN append) { "OPERATOR", "TERM", "REF", "STATE", "BLOCK", "TERMBLOCK" }; #endif -EXT int yychar; /* last token */ - /* yylex @@ -1427,8 +1609,7 @@ EXT int yychar; /* last token */ if we already built the token before, use it. */ -int -yylex(void) +int yylex(PERL_YYLEX_PARAM_DECL) { dTHR; register char *s; @@ -1438,6 +1619,11 @@ yylex(void) GV *gv = Nullgv; GV **gvp = 0; +#ifdef USE_PURE_BISON + yylval_pointer = lvalp; + yychar_pointer = lcharp; +#endif + /* check if there's an identifier for us to look at */ if (PL_pending_ident) { /* pit holds the identifier we read and pending_ident is reset */ @@ -1452,7 +1638,7 @@ yylex(void) */ if (PL_in_my) { if (strchr(PL_tokenbuf,':')) - croak(no_myglob,PL_tokenbuf); + yyerror(form(PL_no_myglob,PL_tokenbuf)); yylval.opval = newOP(OP_PADANY, 0); yylval.opval->op_targ = pad_allocmy(PL_tokenbuf); @@ -1575,7 +1761,7 @@ yylex(void) if (PL_bufptr != PL_bufend) PL_bufptr += 2; PL_lex_state = LEX_INTERPCONCAT; - return yylex(); + return yylex(PERL_YYLEX_PARAM); } else { s = PL_bufptr + 1; @@ -1619,7 +1805,7 @@ yylex(void) Aop(OP_CONCAT); } else - return yylex(); + return yylex(PERL_YYLEX_PARAM); } case LEX_INTERPPUSH: @@ -1652,7 +1838,7 @@ yylex(void) s = PL_bufptr; Aop(OP_CONCAT); } - return yylex(); + return yylex(PERL_YYLEX_PARAM); case LEX_INTERPENDMAYBE: if (intuit_more(PL_bufptr)) { @@ -1667,6 +1853,13 @@ yylex(void) PL_lex_state = LEX_INTERPCONCAT; return ')'; } + if (PL_lex_inwhat == OP_SUBST && PL_linestr == PL_lex_repl + && SvCOMPILED(PL_lex_repl)) + { + if (PL_bufptr != PL_bufend) + croak("Bad evalled substitution pattern"); + PL_lex_repl = Nullsv; + } /* FALLTHROUGH */ case LEX_INTERPCONCAT: #ifdef DEBUGGING @@ -1701,11 +1894,11 @@ yylex(void) Aop(OP_CONCAT); else { PL_bufptr = s; - return yylex(); + return yylex(PERL_YYLEX_PARAM); } } - return yylex(); + return yylex(PERL_YYLEX_PARAM); case LEX_FORMLINE: PL_lex_state = LEX_NORMAL; s = scan_formline(PL_bufptr); @@ -1724,7 +1917,9 @@ yylex(void) retry: switch (*s) { default: - croak("Unrecognized character \\%03o", *s & 255); + if (isIDFIRST_lazy(s)) + goto keylookup; + croak("Unrecognized character \\x%02X", *s & 255); case 4: case 26: goto fake_eof; /* emulate EOF on ^D or ^Z */ @@ -1733,7 +1928,7 @@ yylex(void) PL_last_uni = 0; PL_last_lop = 0; if (PL_lex_brackets) - yyerror("Missing right bracket"); + yyerror("Missing right curly or square bracket"); TOKEN(0); } if (s++ < PL_bufend) @@ -1809,6 +2004,7 @@ yylex(void) else (void)PerlIO_close(PL_rsfp); PL_rsfp = Nullfp; + PL_doextract = FALSE; } if (!PL_in_eval && (PL_minus_n || PL_minus_p)) { sv_setpv(PL_linestr,PL_minus_p ? ";}continue{print" : ""); @@ -1941,7 +2137,7 @@ yylex(void) else newargv = PL_origargv; newargv[0] = ipath; - execv(ipath, newargv); + PerlProc_execv(ipath, newargv); croak("Can't exec %s", ipath); } if (d) { @@ -1982,7 +2178,7 @@ yylex(void) if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) { PL_bufptr = s; PL_lex_state = LEX_FORMLINE; - return yylex(); + return yylex(PERL_YYLEX_PARAM); } goto retry; case '\r': @@ -2006,7 +2202,7 @@ yylex(void) if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) { PL_bufptr = s; PL_lex_state = LEX_FORMLINE; - return yylex(); + return yylex(PERL_YYLEX_PARAM); } } else { @@ -2073,7 +2269,7 @@ yylex(void) else if (*s == '>') { s++; s = skipspace(s); - if (isIDFIRST(*s)) { + if (isIDFIRST_lazy(s)) { s = force_word(s,METHOD,FALSE,TRUE,FALSE); TOKEN(ARROW); } @@ -2176,7 +2372,7 @@ yylex(void) case ']': s++; if (PL_lex_brackets <= 0) - yyerror("Unmatched right bracket"); + yyerror("Unmatched right square bracket"); else --PL_lex_brackets; if (PL_lex_state == LEX_INTERPNORMAL) { @@ -2218,7 +2414,7 @@ yylex(void) while (d < PL_bufend && (*d == ' ' || *d == '\t')) d++; } - if (d < PL_bufend && isIDFIRST(*d)) { + if (d < PL_bufend && isIDFIRST_lazy(d)) { d = scan_word(d, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1, FALSE, &len); while (d < PL_bufend && (*d == ' ' || *d == '\t')) @@ -2306,8 +2502,8 @@ yylex(void) } t++; } - else if (isALPHA(*s)) { - for (t++; t < PL_bufend && isALNUM(*t); t++) ; + else if (isIDFIRST_lazy(s)) { + for (t++; t < PL_bufend && isALNUM_lazy(t); t++) ; } while (t < PL_bufend && isSPACE(*t)) t++; @@ -2317,7 +2513,7 @@ yylex(void) || (*t == '=' && t[1] == '>'))) OPERATOR(HASHBRACK); if (PL_expect == XREF) - PL_expect = XTERM; + PL_expect = XSTATE; /* was XTERM, trying XSTATE */ else { PL_lex_brackstack[PL_lex_brackets-1] = XSTATE; PL_expect = XSTATE; @@ -2333,7 +2529,7 @@ yylex(void) rightbracket: s++; if (PL_lex_brackets <= 0) - yyerror("Unmatched right bracket"); + yyerror("Unmatched right curly bracket"); else PL_expect = (expectation)PL_lex_brackstack[--PL_lex_brackets]; if (PL_lex_brackets < PL_lex_formbrack) @@ -2343,7 +2539,7 @@ yylex(void) if (PL_lex_fakebrack) { PL_lex_state = LEX_INTERPEND; PL_bufptr = s; - return yylex(); /* ignore fake brackets */ + return yylex(PERL_YYLEX_PARAM); /* ignore fake brackets */ } if (*s == '-' && s[1] == '>') PL_lex_state = LEX_INTERPENDMAYBE; @@ -2354,7 +2550,7 @@ yylex(void) if (PL_lex_brackets < PL_lex_fakebrack) { PL_bufptr = s; PL_lex_fakebrack = 0; - return yylex(); /* ignore fake brackets */ + return yylex(PERL_YYLEX_PARAM); /* ignore fake brackets */ } force_next('}'); TOKEN(';'); @@ -2365,9 +2561,9 @@ yylex(void) AOPERATOR(ANDAND); s--; if (PL_expect == XOPERATOR) { - if (PL_dowarn && isALPHA(*s) && PL_bufptr == PL_linestart) { + if (ckWARN(WARN_SEMICOLON) && isIDFIRST_lazy(s) && PL_bufptr == PL_linestart) { PL_curcop->cop_line--; - warn(warn_nosemi); + warner(WARN_SEMICOLON, PL_warn_nosemi); PL_curcop->cop_line++; } BAop(OP_BIT_AND); @@ -2399,8 +2595,8 @@ yylex(void) OPERATOR(','); if (tmp == '~') PMop(OP_MATCH); - if (PL_dowarn && tmp && isSPACE(*s) && strchr("+-*/%.^&|<",tmp)) - warn("Reversed %c= operator",(int)tmp); + if (ckWARN(WARN_SYNTAX) && tmp && isSPACE(*s) && strchr("+-*/%.^&|<",tmp)) + warner(WARN_SYNTAX, "Reversed %c= operator",(int)tmp); s--; if (PL_expect == XSTATE && isALPHA(tmp) && (s == PL_linestart+1 || s[-2] == '\n') ) @@ -2429,7 +2625,11 @@ yylex(void) } if (PL_lex_brackets < PL_lex_formbrack) { char *t; +#ifdef PERL_STRICT_CR for (t = s; *t == ' ' || *t == '\t'; t++) ; +#else + for (t = s; *t == ' ' || *t == '\t' || *t == '\r'; t++) ; +#endif if (*t == '\n' || *t == '#') { s--; PL_expect = XBLOCK; @@ -2491,7 +2691,7 @@ yylex(void) } } - if (s[1] == '#' && (isALPHA(s[2]) || strchr("_{$:", s[2]))) { + if (s[1] == '#' && (isIDFIRST_lazy(s+2) || strchr("{$:+-", s[2]))) { if (PL_expect == XOPERATOR) no_op("Array length", PL_bufptr); PL_tokenbuf[0] = '@'; @@ -2523,6 +2723,7 @@ yylex(void) } d = s; + tmp = (I32)*s; if (PL_lex_state == LEX_NORMAL) s = skipspace(s); @@ -2530,46 +2731,49 @@ yylex(void) char *t; if (*s == '[') { PL_tokenbuf[0] = '@'; - if (PL_dowarn) { + if (ckWARN(WARN_SYNTAX)) { for(t = s + 1; - isSPACE(*t) || isALNUM(*t) || *t == '$'; + isSPACE(*t) || isALNUM_lazy(t) || *t == '$'; t++) ; if (*t++ == ',') { PL_bufptr = skipspace(PL_bufptr); while (t < PL_bufend && *t != ']') t++; - warn("Multidimensional syntax %.*s not supported", - (t - PL_bufptr) + 1, PL_bufptr); + warner(WARN_SYNTAX, + "Multidimensional syntax %.*s not supported", + (t - PL_bufptr) + 1, PL_bufptr); } } } else if (*s == '{') { PL_tokenbuf[0] = '%'; - if (PL_dowarn && strEQ(PL_tokenbuf+1, "SIG") && + if (ckWARN(WARN_SYNTAX) && strEQ(PL_tokenbuf+1, "SIG") && (t = strchr(s, '}')) && (t = strchr(t, '='))) { char tmpbuf[sizeof PL_tokenbuf]; STRLEN len; for (t++; isSPACE(*t); t++) ; - if (isIDFIRST(*t)) { + if (isIDFIRST_lazy(t)) { t = scan_word(t, tmpbuf, sizeof tmpbuf, TRUE, &len); - if (*t != '(' && perl_get_cv(tmpbuf, FALSE)) - warn("You need to quote \"%s\"", tmpbuf); + for (; isSPACE(*t); t++) ; + if (*t == ';' && perl_get_cv(tmpbuf, FALSE)) + warner(WARN_SYNTAX, + "You need to quote \"%s\"", tmpbuf); } } } } PL_expect = XOPERATOR; - if (PL_lex_state == LEX_NORMAL && isSPACE(*d)) { + if (PL_lex_state == LEX_NORMAL && isSPACE((char)tmp)) { bool islop = (PL_last_lop == PL_oldoldbufptr); if (!islop || PL_last_lop_op == OP_GREPSTART) PL_expect = XOPERATOR; else if (strchr("$@\"'`q", *s)) PL_expect = XTERM; /* e.g. print $fh "foo" */ - else if (strchr("&*<%", *s) && isIDFIRST(s[1])) + else if (strchr("&*<%", *s) && isIDFIRST_lazy(s+1)) PL_expect = XTERM; /* e.g. print $fh &sub */ - else if (isIDFIRST(*s)) { + else if (isIDFIRST_lazy(s)) { char tmpbuf[sizeof PL_tokenbuf]; scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len); if (tmp = keyword(tmpbuf, len)) { @@ -2599,9 +2803,9 @@ yylex(void) PL_expect = XTERM; /* e.g. print $fh 3 */ else if (*s == '.' && isDIGIT(s[1])) PL_expect = XTERM; /* e.g. print $fh .3 */ - else if (strchr("/?-+", *s) && !isSPACE(s[1])) + else if (strchr("/?-+", *s) && !isSPACE(s[1]) && s[1] != '=') PL_expect = XTERM; /* e.g. print $fh -1 */ - else if (*s == '<' && s[1] == '<' && !isSPACE(s[2])) + else if (*s == '<' && s[1] == '<' && !isSPACE(s[2]) && s[2] != '=') PL_expect = XTERM; /* print $fh <<"EOF" */ } PL_pending_ident = '$'; @@ -2624,15 +2828,16 @@ yylex(void) PL_tokenbuf[0] = '%'; /* Warn about @ where they meant $. */ - if (PL_dowarn) { + if (ckWARN(WARN_SYNTAX)) { if (*s == '[' || *s == '{') { char *t = s + 1; - while (*t && (isALNUM(*t) || strchr(" \t$#+-'\"", *t))) + while (*t && (isALNUM_lazy(t) || strchr(" \t$#+-'\"", *t))) t++; if (*t == '}' || *t == ']') { t++; PL_bufptr = skipspace(PL_bufptr); - warn("Scalar value %.*s better written as $%.*s", + warner(WARN_SYNTAX, + "Scalar value %.*s better written as $%.*s", t-PL_bufptr, PL_bufptr, t-PL_bufptr-1, PL_bufptr+1); } } @@ -2647,7 +2852,7 @@ yylex(void) /* 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(PL_last_uni[5]))) + || memNE(PL_last_uni, "study", 5) || isALNUM_lazy(PL_last_uni+5))) check_uni(); s = scan_pat(s,OP_MATCH); TERM(sublex_start()); @@ -2658,8 +2863,14 @@ yylex(void) OPERATOR(tmp); case '.': - if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack && s[1] == '\n' && - (s == PL_linestart || s[-1] == '\n') ) { + if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack +#ifdef PERL_STRICT_CR + && s[1] == '\n' +#else + && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')) +#endif + && (s == PL_linestart || s[-1] == '\n') ) + { PL_lex_formbrack = 0; PL_expect = XSTATE; goto rightbracket; @@ -2719,7 +2930,7 @@ yylex(void) missingterm((char*)0); yylval.ival = OP_CONST; for (d = SvPV(PL_lex_stuff, len); len; len--, d++) { - if (*d == '$' || *d == '@' || *d == '\\') { + if (*d == '$' || *d == '@' || *d == '\\' || *d & 0x80) { yylval.ival = OP_STRINGIFY; break; } @@ -2738,8 +2949,9 @@ yylex(void) case '\\': s++; - if (PL_dowarn && PL_lex_inwhat && isDIGIT(*s)) - warn("Can't use \\%c to mean $%c in expression", *s, *s); + if (ckWARN(WARN_SYNTAX) && PL_lex_inwhat && isDIGIT(*s)) + warner(WARN_SYNTAX,"Can't use \\%c to mean $%c in expression", + *s, *s); if (PL_expect == XOPERATOR) no_op("Backslash",s); OPERATOR(REFGEN); @@ -2780,6 +2992,7 @@ yylex(void) case 'z': case 'Z': keylookup: { + STRLEN n_a; gv = Nullgv; gvp = 0; @@ -2854,8 +3067,10 @@ yylex(void) tmp = -tmp; gv = Nullgv; gvp = 0; - if (PL_dowarn && hgv) - warn("Ambiguous call resolved as CORE::%s(), %s", + if (ckWARN(WARN_AMBIGUOUS) && hgv + && tmp != KEY_x && tmp != KEY_CORE) /* never ambiguous */ + warner(WARN_AMBIGUOUS, + "Ambiguous call resolved as CORE::%s(), %s", GvENAME(hgv), "qualify as such or use &"); } } @@ -2883,7 +3098,7 @@ yylex(void) if (PL_expect == XOPERATOR) { if (PL_bufptr == PL_linestart) { PL_curcop->cop_line--; - warn(warn_nosemi); + warner(WARN_SEMICOLON, PL_warn_nosemi); PL_curcop->cop_line++; } else @@ -2897,8 +3112,9 @@ yylex(void) if (len > 2 && PL_tokenbuf[len - 2] == ':' && PL_tokenbuf[len - 1] == ':') { - if (PL_dowarn && ! gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVHV)) - warn("Bareword \"%s\" refers to nonexistent package", + if (ckWARN(WARN_UNSAFE) && ! gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVHV)) + warner(WARN_UNSAFE, + "Bareword \"%s\" refers to nonexistent package", PL_tokenbuf); len -= 2; PL_tokenbuf[len] = '\0'; @@ -2914,7 +3130,7 @@ yylex(void) /* if we saw a global override before, get the right name */ if (gvp) { - sv = newSVpv("CORE::GLOBAL::",14); + sv = newSVpvn("CORE::GLOBAL::",14); sv_catpv(sv,PL_tokenbuf); } else @@ -2938,7 +3154,7 @@ yylex(void) (PL_oldoldbufptr == PL_last_lop || PL_oldoldbufptr == PL_last_uni) && /* NO SKIPSPACE BEFORE HERE! */ (PL_expect == XREF - || ((opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF + || ((PL_opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF || (PL_last_lop_op == OP_ENTERSUB && PL_last_proto && PL_last_proto[PL_last_proto[0] == ';' ? 1 : 0] == '*')) ) @@ -2950,7 +3166,7 @@ yylex(void) /* Two barewords in a row may indicate method call. */ - if ((isALPHA(*s) || *s == '$') && (tmp=intuit_method(s,gv))) + if ((isIDFIRST_lazy(s) || *s == '$') && (tmp=intuit_method(s,gv))) return tmp; /* If not a declared subroutine, it's an indirect object. */ @@ -2971,8 +3187,11 @@ yylex(void) if (*s == '(') { CLINE; if (gv && GvCVu(gv)) { + CV *cv; + if ((cv = GvCV(gv)) && SvPOK(cv)) + PL_last_proto = SvPV((SV*)cv, n_a); for (d = s + 1; *d == ' ' || *d == '\t'; d++) ; - if (*d == ')' && (sv = cv_const_sv(GvCV(gv)))) { + if (*d == ')' && (sv = cv_const_sv(cv))) { s = d + 1; goto its_constant; } @@ -2981,6 +3200,7 @@ yylex(void) PL_expect = XOPERATOR; force_next(WORD); yylval.ival = 0; + PL_last_lop_op = OP_ENTERSUB; TOKEN('&'); } @@ -2994,7 +3214,7 @@ yylex(void) /* If followed by a bareword, see if it looks like indir obj. */ - if ((isALPHA(*s) || *s == '$') && (tmp = intuit_method(s,gv))) + if ((isIDFIRST_lazy(s) || *s == '$') && (tmp = intuit_method(s,gv))) return tmp; /* Not a method, so call it a subroutine (if defined) */ @@ -3019,6 +3239,7 @@ yylex(void) /* Resolve to GV now. */ op_free(yylval.opval); yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv)); + PL_last_lop_op = OP_ENTERSUB; /* Is there a prototype? */ if (SvPOK(cv)) { STRLEN len; @@ -3045,7 +3266,10 @@ yylex(void) PL_last_lop_op != OP_TRUNCATE && /* S/F prototype in opcode.pl */ PL_last_lop_op != OP_ACCEPT && PL_last_lop_op != OP_PIPE_OP && - PL_last_lop_op != OP_SOCKPAIR) + PL_last_lop_op != OP_SOCKPAIR && + !(PL_last_lop_op == OP_ENTERSUB + && PL_last_proto + && PL_last_proto[PL_last_proto[0] == ';' ? 1 : 0] == '*')) { warn( "Bareword \"%s\" not allowed while \"strict subs\" in use", @@ -3056,11 +3280,11 @@ yylex(void) /* Call it a bare word */ bareword: - if (PL_dowarn) { + if (ckWARN(WARN_RESERVED)) { if (lastchar != '-') { for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ; if (!*d) - warn(warn_reserved, PL_tokenbuf); + warner(WARN_RESERVED, PL_warn_reserved, PL_tokenbuf); } } @@ -3201,7 +3425,7 @@ yylex(void) LOP(OP_CRYPT,XTERM); case KEY_chmod: - if (PL_dowarn) { + if (ckWARN(WARN_OCTAL)) { for (d = s; d < PL_bufend && (isSPACE(*d) || *d == '('); d++) ; if (*d != '0' && isDIGIT(*d)) yywarn("chmod: mode argument is missing initial 0"); @@ -3308,13 +3532,13 @@ yylex(void) case KEY_foreach: yylval.ival = PL_curcop->cop_line; s = skipspace(s); - if (PL_expect == XSTATE && isIDFIRST(*s)) { + if (PL_expect == XSTATE && isIDFIRST_lazy(s)) { char *p = s; if ((PL_bufend - p) >= 3 && strnEQ(p, "my", 2) && isSPACE(*(p + 2))) p += 2; p = skipspace(p); - if (isIDFIRST(*p)) + if (isIDFIRST_lazy(p)) croak("Missing $ on loop variable"); } OPERATOR(FOR); @@ -3502,7 +3726,7 @@ yylex(void) TERM(sublex_start()); case KEY_map: - LOP(OP_MAPSTART,XREF); + LOP(OP_MAPSTART, XREF); case KEY_mkdir: LOP(OP_MKDIR,XTERM); @@ -3522,7 +3746,7 @@ yylex(void) case KEY_my: PL_in_my = TRUE; s = skipspace(s); - if (isIDFIRST(*s)) { + if (isIDFIRST_lazy(s)) { s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, TRUE, &len); PL_in_my_stash = gv_stashpv(PL_tokenbuf, FALSE); if (!PL_in_my_stash) { @@ -3554,9 +3778,9 @@ yylex(void) case KEY_open: s = skipspace(s); - if (isIDFIRST(*s)) { + if (isIDFIRST_lazy(s)) { char *t; - for (d = s; isALNUM(*d); d++) ; + for (d = s; isALNUM_lazy(d); d++) ; t = skipspace(d); if (strchr("|&*+-=!?:.", *t)) warn("Precedence problem: open %.*s should be open(%.*s)", @@ -3621,34 +3845,46 @@ yylex(void) s = scan_str(s); if (!s) missingterm((char*)0); - if (PL_dowarn && SvLEN(PL_lex_stuff)) { + force_next(')'); + if (SvCUR(PL_lex_stuff)) { + OP *words = Nullop; + int warned = 0; d = SvPV_force(PL_lex_stuff, len); - for (; len; --len, ++d) { - if (*d == ',') { - warn("Possible attempt to separate words with commas"); - break; - } - if (*d == '#') { - warn("Possible attempt to put comments in qw() list"); - break; + while (len) { + for (; isSPACE(*d) && len; --len, ++d) ; + if (len) { + char *b = d; + if (!warned && ckWARN(WARN_SYNTAX)) { + for (; !isSPACE(*d) && len; --len, ++d) { + if (*d == ',') { + warner(WARN_SYNTAX, + "Possible attempt to separate words with commas"); + ++warned; + } + else if (*d == '#') { + warner(WARN_SYNTAX, + "Possible attempt to put comments in qw() list"); + ++warned; + } + } + } + else { + for (; !isSPACE(*d) && len; --len, ++d) ; + } + words = append_elem(OP_LIST, words, + newSVOP(OP_CONST, 0, newSVpvn(b, d-b))); } } + if (words) { + PL_nextval[PL_nexttoke].opval = words; + force_next(THING); + } } - force_next(')'); - PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, tokeq(PL_lex_stuff)); + if (PL_lex_stuff) + SvREFCNT_dec(PL_lex_stuff); PL_lex_stuff = Nullsv; - force_next(THING); - force_next(','); - PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(" ",1)); - force_next(THING); - force_next('('); - yylval.ival = OP_SPLIT; - CLINE; PL_expect = XTERM; - PL_bufptr = s; - PL_last_lop = PL_oldbufptr; - PL_last_lop_op = OP_SPLIT; - return FUNC; + TOKEN('('); case KEY_qq: s = scan_str(s); @@ -3677,7 +3913,7 @@ yylex(void) case KEY_require: *PL_tokenbuf = '\0'; s = force_word(s,WORD,TRUE,TRUE,FALSE); - if (isIDFIRST(*PL_tokenbuf)) + if (isIDFIRST_lazy(PL_tokenbuf)) gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE); else if (*s == '<') yyerror("<> should be quotes"); @@ -3861,7 +4097,7 @@ yylex(void) really_sub: s = skipspace(s); - if (isIDFIRST(*s) || *s == '\'' || *s == ':') { + if (isIDFIRST_lazy(s) || *s == '\'' || *s == ':') { char tmpbuf[sizeof PL_tokenbuf]; PL_expect = XBLOCK; d = scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len); @@ -3921,7 +4157,7 @@ yylex(void) PL_lex_stuff = Nullsv; } - if (*SvPV(PL_subname,PL_na) == '?') { + if (*SvPV(PL_subname,n_a) == '?') { sv_setpv(PL_subname,"__ANON__"); TOKEN(ANONSUB); } @@ -4004,7 +4240,7 @@ yylex(void) LOP(OP_UTIME,XTERM); case KEY_umask: - if (PL_dowarn) { + if (ckWARN(WARN_OCTAL)) { for (d = s; d < PL_bufend && (isSPACE(*d) || *d == '('); d++) ; if (*d != '0' && isDIGIT(*d)) yywarn("umask: argument is missing initial 0"); @@ -4057,7 +4293,17 @@ yylex(void) FUN0(OP_WANTARRAY); case KEY_write: - gv_fetchpv("\f",TRUE, SVt_PV); /* Make sure $^L is defined */ +#ifdef EBCDIC + { + static char ctl_l[2]; + + if (ctl_l[0] == '\0') + ctl_l[0] = toCTRL('L'); + gv_fetchpv(ctl_l,TRUE, SVt_PV); + } +#else + gv_fetchpv("\f",TRUE, SVt_PV); /* Make sure $^L is defined */ +#endif UNI(OP_ENTERWRITE); case KEY_x: @@ -4701,18 +4947,21 @@ checkcomma(register char *s, char *name, char *what) { char *w; - if (PL_dowarn && *s == ' ' && s[1] == '(') { /* XXX gotta be a better way */ - int level = 1; - for (w = s+2; *w && level; w++) { - if (*w == '(') - ++level; - else if (*w == ')') - --level; - } - if (*w) - for (; *w && isSPACE(*w); w++) ; - if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */ - warn("%s (...) interpreted as function",name); + if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way */ + dTHR; /* only for ckWARN */ + if (ckWARN(WARN_SYNTAX)) { + int level = 1; + for (w = s+2; *w && level; w++) { + if (*w == '(') + ++level; + else if (*w == ')') + --level; + } + if (*w) + for (; *w && isSPACE(*w); w++) ; + if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */ + warner(WARN_SYNTAX, "%s (...) interpreted as function",name); + } } while (s < PL_bufend && isSPACE(*s)) s++; @@ -4720,9 +4969,9 @@ checkcomma(register char *s, char *name, char *what) s++; while (s < PL_bufend && isSPACE(*s)) s++; - if (isIDFIRST(*s)) { + if (isIDFIRST_lazy(s)) { w = s++; - while (isALNUM(*s)) + while (isALNUM_lazy(s)) s++; while (s < PL_bufend && isSPACE(*s)) s++; @@ -4748,7 +4997,6 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) bool oldcatch = CATCH_GET; SV **cvp; SV *cv, *typesv; - char buf[128]; if (!table) { yyerror("%^H is not defined"); @@ -4756,6 +5004,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) } cvp = hv_fetch(table, key, strlen(key), FALSE); if (!cvp || !SvOK(*cvp)) { + char buf[128]; sprintf(buf,"$^H{%s} is not defined", key); yyerror(buf); return sv; @@ -4763,7 +5012,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) sv_2mortal(sv); /* Parent created it permanently */ cv = *cvp; if (!pv) - pv = sv_2mortal(newSVpv(s, len)); + pv = sv_2mortal(newSVpvn(s, len)); if (type) typesv = sv_2mortal(newSVpv(type, 0)); else @@ -4801,6 +5050,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) POPSTACK; if (!SvOK(res)) { + char buf[128]; sprintf(buf,"Call to &{$^H{%s}} did not return a defined value", key); yyerror(buf); } @@ -4815,9 +5065,9 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE for (;;) { if (d >= e) croak(ident_too_long); - if (isALNUM(*s)) + if (isALNUM(*s)) /* UTF handled below */ *d++ = *s++; - else if (*s == '\'' && allow_package && isIDFIRST(s[1])) { + else if (*s == '\'' && allow_package && isIDFIRST_lazy(s+1)) { *d++ = ':'; *d++ = ':'; s++; @@ -4826,6 +5076,16 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE *d++ = *s++; *d++ = *s++; } + else if (UTF && *(U8*)s >= 0xc0 && isALNUM_utf8((U8*)s)) { + char *t = s + UTF8SKIP(s); + while (*t & 0x80 && is_utf8_mark((U8*)t)) + t += UTF8SKIP(t); + if (d + (t - s) > e) + croak(ident_too_long); + Copy(s, d, t - s, char); + d += t - s; + s = t; + } else { *d = '\0'; *slp = d - dest; @@ -4859,9 +5119,9 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 for (;;) { if (d >= e) croak(ident_too_long); - if (isALNUM(*s)) + if (isALNUM(*s)) /* UTF handled below */ *d++ = *s++; - else if (*s == '\'' && isIDFIRST(s[1])) { + else if (*s == '\'' && isIDFIRST_lazy(s+1)) { *d++ = ':'; *d++ = ':'; s++; @@ -4870,6 +5130,16 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 *d++ = *s++; *d++ = *s++; } + else if (UTF && *(U8*)s >= 0xc0 && isALNUM_utf8((U8*)s)) { + char *t = s + UTF8SKIP(s); + while (*t & 0x80 && is_utf8_mark((U8*)t)) + t += UTF8SKIP(t); + if (d + (t - s) > e) + croak(ident_too_long); + Copy(s, d, t - s, char); + d += t - s; + s = t; + } else break; } @@ -4882,12 +5152,9 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 return s; } if (*s == '$' && s[1] && - (isALNUM(s[1]) || strchr("${", s[1]) || strnEQ(s+1,"::",2)) ) + (isALNUM_lazy(s+1) || strchr("${", s[1]) || strnEQ(s+1,"::",2)) ) { - if (isDIGIT(s[1]) && PL_lex_state == LEX_INTERPNORMAL) - deprecate("\"$$\" to mean \"${$}\""); - else - return s; + return s; } if (*s == '{') { bracket = s; @@ -4898,7 +5165,7 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 if (s < send) *d = *s++; d[1] = '\0'; - if (*d == '^' && *s && (isUPPER(*s) || strchr("[\\]^_?", *s))) { + if (*d == '^' && *s && isCONTROLVAR(*s)) { *d = toCTRL(*s); s++; } @@ -4912,16 +5179,33 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 } } } - if (isIDFIRST(*d)) { + if (isIDFIRST_lazy(d)) { d++; - while (isALNUM(*s) || *s == ':') - *d++ = *s++; + if (UTF) { + e = s; + while (e < send && isALNUM_lazy(e) || *e == ':') { + e += UTF8SKIP(e); + while (e < send && *e & 0x80 && is_utf8_mark((U8*)e)) + e += UTF8SKIP(e); + } + Copy(s, d, e - s, char); + d += e - s; + s = e; + } + else { + while ((isALNUM(*s) || *s == ':') && d < e) + *d++ = *s++; + if (d >= e) + croak(ident_too_long); + } *d = '\0'; while (s < send && (*s == ' ' || *s == '\t')) s++; if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) { - if (PL_dowarn && keyword(dest, d - dest)) { + dTHR; /* only for ckWARN */ + if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) { char *brack = *s == '[' ? "[...]" : "{...}"; - warn("Ambiguous use of %c{%s%s} resolved to %c%s%s", + warner(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; @@ -4929,6 +5213,19 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR; return s; } + } + /* Handle extended ${^Foo} variables + * 1999-02-27 mjd-perl-patch@plover.com */ + else if (!isALNUM(*d) && !isPRINT(*d) /* isCTRL(d) */ + && isALNUM(*s)) + { + d++; + while (isALNUM(*s) && d < e) { + *d++ = *s++; + } + if (d >= e) + croak(ident_too_long); + *d = '\0'; } if (*s == '}') { s++; @@ -4936,10 +5233,16 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3 PL_lex_state = LEX_INTERPEND; if (funny == '#') funny = '@'; - if (PL_dowarn && PL_lex_state == LEX_NORMAL && - (keyword(dest, d - dest) || perl_get_cv(dest, FALSE))) - warn("Ambiguous use of %c{%s} resolved to %c%s", - funny, dest, funny, dest); + if (PL_lex_state == LEX_NORMAL) { + dTHR; /* only for ckWARN */ + if (ckWARN(WARN_AMBIGUOUS) && + (keyword(dest, d - dest) || perl_get_cv(dest, FALSE))) + { + warner(WARN_AMBIGUOUS, + "Ambiguous use of %c{%s} resolved to %c%s", + funny, dest, funny, dest); + } + } } else { s = bracket; /* let the parser handle it */ @@ -5050,8 +5353,11 @@ scan_subst(char *start) if (es) { SV *repl; + PL_sublex_info.super_bufptr = s; + PL_sublex_info.super_bufend = PL_bufend; + PL_multi_end = 0; pm->op_pmflags |= PMf_EVAL; - repl = newSVpv("",0); + repl = newSVpvn("",0); while (es-- > 0) sv_catpv(repl, es ? "eval " : "do "); sv_catpvn(repl, "{ ", 2); @@ -5075,8 +5381,10 @@ scan_trans(char *start) OP *o; short *tbl; I32 squash; - I32 Delete; + I32 del; I32 complement; + I32 utf8; + I32 count = 0; yylval.ival = OP_NULL; @@ -5101,20 +5409,45 @@ scan_trans(char *start) croak("Transliteration replacement not terminated"); } - New(803,tbl,256,short); - o = newPVOP(OP_TRANS, 0, (char*)tbl); + if (UTF) { + o = newSVOP(OP_TRANS, 0, 0); + utf8 = OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF; + } + else { + New(803,tbl,256,short); + o = newPVOP(OP_TRANS, 0, (char*)tbl); + utf8 = 0; + } - complement = Delete = squash = 0; - while (*s == 'c' || *s == 'd' || *s == 's') { + complement = del = squash = 0; + while (strchr("cdsCU", *s)) { if (*s == 'c') complement = OPpTRANS_COMPLEMENT; else if (*s == 'd') - Delete = OPpTRANS_DELETE; - else + del = OPpTRANS_DELETE; + else if (*s == 's') squash = OPpTRANS_SQUASH; + else { + switch (count++) { + case 0: + if (*s == 'C') + utf8 &= ~OPpTRANS_FROM_UTF; + else + utf8 |= OPpTRANS_FROM_UTF; + break; + case 1: + if (*s == 'C') + utf8 &= ~OPpTRANS_TO_UTF; + else + utf8 |= OPpTRANS_TO_UTF; + break; + default: + croak("Too many /C and /U options"); + } + } s++; } - o->op_private = Delete|squash|complement; + o->op_private = del|squash|complement|utf8; PL_lex_op = o; yylval.ival = OP_TRANS; @@ -5154,9 +5487,9 @@ scan_heredoc(register char *s) s++, term = '\''; else term = '"'; - if (!isALNUM(*s)) + if (!isALNUM_lazy(s)) deprecate("bare << to mean <<\"\""); - for (; isALNUM(*s); s++) { + for (; isALNUM_lazy(s); s++) { if (d < e) *d++ = *s; } @@ -5192,9 +5525,9 @@ scan_heredoc(register char *s) #endif d = "\n"; if (outer || !(d=ninstr(s,PL_bufend,d,d+1))) - herewas = newSVpv(s,PL_bufend-s); + herewas = newSVpvn(s,PL_bufend-s); else - s--, herewas = newSVpv(s,d-s); + s--, herewas = newSVpvn(s,d-s); s += SvCUR(herewas); tmpstr = NEWSV(87,79); @@ -5212,7 +5545,33 @@ scan_heredoc(register char *s) PL_multi_start = PL_curcop->cop_line; PL_multi_open = PL_multi_close = '<'; term = *PL_tokenbuf; - if (!outer) { + if (PL_lex_inwhat == OP_SUBST && PL_in_eval && !PL_rsfp) { + char *bufptr = PL_sublex_info.super_bufptr; + char *bufend = PL_sublex_info.super_bufend; + char *olds = s - SvCUR(herewas); + s = strchr(bufptr, '\n'); + if (!s) + s = bufend; + d = s; + while (s < bufend && + (*s != term || memNE(s,PL_tokenbuf,len)) ) { + if (*s++ == '\n') + PL_curcop->cop_line++; + } + if (s >= bufend) { + PL_curcop->cop_line = PL_multi_start; + missingterm(PL_tokenbuf); + } + sv_setpvn(herewas,bufptr,d-bufptr+1); + sv_setpvn(tmpstr,d+1,s-d); + s += len - 1; + sv_catpvn(herewas,s,bufend-s); + (void)strcpy(bufptr,SvPVX(herewas)); + + s = olds; + goto retval; + } + else if (!outer) { d = s; while (s < PL_bufend && (*s != term || memNE(s,PL_tokenbuf,len)) ) { @@ -5276,8 +5635,9 @@ scan_heredoc(register char *s) sv_catsv(tmpstr,PL_linestr); } } - PL_multi_end = PL_curcop->cop_line; s++; +retval: + PL_multi_end = PL_curcop->cop_line; if (SvCUR(tmpstr) + 5 < SvLEN(tmpstr)) { SvLEN_set(tmpstr, SvCUR(tmpstr) + 1); Renew(SvPVX(tmpstr), SvLEN(tmpstr), char); @@ -5310,19 +5670,23 @@ scan_inputsymbol(char *start) register char *s = start; /* current position in buffer */ register char *d; register char *e; + char *end; I32 len; d = PL_tokenbuf; /* start of temp holding space */ e = PL_tokenbuf + sizeof PL_tokenbuf; /* end of temp holding space */ - s = delimcpy(d, e, s + 1, PL_bufend, '>', &len); /* extract until > */ + end = strchr(s, '\n'); + if (!end) + end = PL_bufend; + s = delimcpy(d, e, s + 1, end, '>', &len); /* extract until > */ /* die if we didn't have space for the contents of the <>, - or if it didn't end + or if it didn't end, or if we see a newline */ if (len >= sizeof PL_tokenbuf) croak("Excessively long <> operator"); - if (s >= PL_bufend) + if (s >= end) croak("Unterminated <> operator"); s++; @@ -5337,7 +5701,7 @@ scan_inputsymbol(char *start) if (*d == '$' && d[1]) d++; /* allow or */ - while (*d && (isALNUM(*d) || *d == '\'' || *d == ':')) + while (*d && (isALNUM_lazy(d) || *d == '\'' || *d == ':')) d++; /* If we've tried to read what we allow filehandles to look like, and @@ -5374,16 +5738,16 @@ scan_inputsymbol(char *start) if ((tmp = pad_findmy(d)) != NOT_IN_PAD) { OP *o = newOP(OP_PADSV, 0); o->op_targ = tmp; - PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, newUNOP(OP_RV2GV, 0, o)); + PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, o); } else { GV *gv = gv_fetchpv(d+1,TRUE, SVt_PV); PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, - newUNOP(OP_RV2GV, 0, newUNOP(OP_RV2SV, 0, - newGVOP(OP_GV, 0, gv)))); + newGVOP(OP_GV, 0, gv))); } - /* we created the ops in lex_op, so make yylval.ival a null op */ + 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; } @@ -5568,7 +5932,7 @@ scan_str(char *start) } /* we read a line, so increment our line counter */ PL_curcop->cop_line++; - + /* update debugger info */ if (PERLDB_LINE && PL_curstash != PL_debstash) { SV *sv = NEWSV(88,0); @@ -5578,7 +5942,7 @@ scan_str(char *start) av_store(GvAV(PL_curcop->cop_filegv), (I32)PL_curcop->cop_line, sv); } - + /* having changed the buffer, we must update PL_bufend */ PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr); } @@ -5613,7 +5977,7 @@ scan_str(char *start) Read a number in any of the formats that Perl accepts: - 0(x[0-7A-F]+)|([0-7]+) + 0(x[0-7A-F]+)|([0-7]+)|(b[01]) [\d_]+(\.[\d_]*)?[Ee](\d+) Underbars (_) are allowed in decimal numbers. If -w is on, @@ -5647,18 +6011,19 @@ scan_num(char *start) croak("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. + 0.13 disguise, or a hexadecimal number, or a binary number. */ case '0': { /* variables: u holds the "number so far" - shift the power of 2 of the base (hex == 4, octal == 3) + shift the power of 2 of the base + (hex == 4, octal == 3, binary == 1) overflowed was the number more than we can hold? Shift is used when we add a digit. It also serves as an "are - we in octal or hex?" indicator to disallow hex characters when - in octal mode. + we in octal/hex/binary?" indicator to disallow hex characters + when in octal mode. */ UV u; I32 shift; @@ -5668,6 +6033,9 @@ scan_num(char *start) if (s[1] == 'x') { shift = 4; s += 2; + } else if (s[1] == 'b') { + shift = 1; + s += 2; } /* check for a decimal in disguise */ else if (s[1] == '.') @@ -5677,7 +6045,7 @@ scan_num(char *start) shift = 3; u = 0; - /* read the rest of the octal number */ + /* read the rest of the number */ for (;;) { UV n, b; /* n is used in the overflow test, b is the digit we're adding on */ @@ -5694,13 +6062,21 @@ scan_num(char *start) /* 8 and 9 are not octal */ case '8': case '9': - if (shift != 4) - yyerror("Illegal octal digit"); + if (shift == 3) + yyerror(form("Illegal octal digit '%c'", *s)); + else + if (shift == 1) + yyerror(form("Illegal binary digit '%c'", *s)); /* FALL THROUGH */ /* octal digits */ - case '0': case '1': case '2': case '3': case '4': + case '2': case '3': case '4': case '5': case '6': case '7': + if (shift == 1) + yyerror(form("Illegal binary digit '%c'", *s)); + /* FALL THROUGH */ + + case '0': case '1': b = *s++ & 15; /* ASCII digit -> value of digit */ goto digit; @@ -5721,7 +6097,8 @@ scan_num(char *start) if (!overflowed && (n >> shift) != u && !(PL_hints & HINT_NEW_BINARY)) { warn("Integer overflow in %s number", - (shift == 4) ? "hex" : "octal"); + (shift == 4) ? "hex" + : ((shift == 3) ? "octal" : "binary")); overflowed = TRUE; } u = n | b; /* add the digit to the end */ @@ -5757,8 +6134,9 @@ scan_num(char *start) if -w is on */ if (*s == '_') { - if (PL_dowarn && lastub && s - lastub != 3) - warn("Misplaced _ in number"); + dTHR; /* only for ckWARN */ + if (ckWARN(WARN_SYNTAX) && lastub && s - lastub != 3) + warner(WARN_SYNTAX, "Misplaced _ in number"); lastub = ++s; } else { @@ -5771,8 +6149,11 @@ scan_num(char *start) } /* final misplaced underbar check */ - if (PL_dowarn && lastub && s - lastub != 3) - warn("Misplaced _ in number"); + if (lastub && s - lastub != 3) { + dTHR; + if (ckWARN(WARN_SYNTAX)) + warner(WARN_SYNTAX, "Misplaced _ in number"); + } /* read a decimal portion if there is one. avoid 3..5 being interpreted as the number 3. followed @@ -5857,14 +6238,18 @@ scan_formline(register char *s) dTHR; register char *eol; register char *t; - SV *stuff = newSVpv("",0); + SV *stuff = newSVpvn("",0); bool needargs = FALSE; while (!needargs) { if (*s == '.' || *s == '}') { /*SUPPRESS 530*/ - for (t = s+1; *t == ' ' || *t == '\t'; t++) ; - if (*t == '\n') +#ifdef PERL_STRICT_CR + for (t = s+1;*t == ' ' || *t == '\t'; t++) ; +#else + for (t = s+1;*t == ' ' || *t == '\t' || *t == '\r'; t++) ; +#endif + if (*t == '\n' || t == PL_bufend) break; } if (PL_in_eval && !PL_rsfp) { @@ -5966,7 +6351,7 @@ start_subparse(I32 is_format, U32 flags) PL_padix = 0; PL_subline = PL_curcop->cop_line; #ifdef USE_THREADS - av_store(PL_comppad_name, 0, newSVpv("@_", 2)); + av_store(PL_comppad_name, 0, newSVpvn("@_", 2)); PL_curpad[0] = (SV*)newAV(); SvPADMY_on(PL_curpad[0]); /* XXX Needed? */ #endif /* USE_THREADS */ @@ -6035,7 +6420,7 @@ yyerror(char *s) where = "within string"; } else { - SV *where_sv = sv_2mortal(newSVpv("next char ", 0)); + SV *where_sv = sv_2mortal(newSVpvn("next char ", 10)); if (yychar < 32) sv_catpvf(where_sv, "^%c", toCTRL(yychar)); else if (isPRINT_LC(yychar))