#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));
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))
/* 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).
#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
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;
}
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;
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;
start = skipspace(start);
s = start;
- if (isIDFIRST(*s) ||
+ if (isIDFIRST_lazy(s) ||
(allow_pack && *s == ':') ||
(allow_initial_tick && *s == '\'') )
{
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));
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? */
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 {
/* 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)) {
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++;
}
}
}
/* 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
s++;
/* some backslashes we leave behind */
- if (*s && strchr(leaveit, *s)) {
+ if (*leaveit && *s && strchr(leaveit, *s)) {
*d++ = '\\';
*d++ = *s++;
continue;
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':
if (*s == '{') {
char* e = strchr(s, '}');
- if (!e)
+ if (!e) {
yyerror("Missing right brace on \\x{}");
+ e = s;
+ }
if (!utf) {
dTHR;
if (ckWARN(WARN_UTF8))
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;
* 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)
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);
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;
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 */
}
/* 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 */
{ "OPERATOR", "TERM", "REF", "STATE", "BLOCK", "TERMBLOCK" };
#endif
-EXT int yychar; /* last token */
-
/*
yylex
if we already built the token before, use it.
*/
-int
-yylex(void)
+int yylex(PERL_YYLEX_PARAM_DECL)
{
dTHR;
register char *s;
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 */
*/
if (PL_in_my) {
if (strchr(PL_tokenbuf,':'))
- croak(no_myglob,PL_tokenbuf);
+ croak(PL_no_myglob,PL_tokenbuf);
yylval.opval = newOP(OP_PADANY, 0);
yylval.opval->op_targ = pad_allocmy(PL_tokenbuf);
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;
Aop(OP_CONCAT);
}
else
- return yylex();
+ return yylex(PERL_YYLEX_PARAM);
}
case LEX_INTERPPUSH:
s = PL_bufptr;
Aop(OP_CONCAT);
}
- return yylex();
+ return yylex(PERL_YYLEX_PARAM);
case LEX_INTERPENDMAYBE:
if (intuit_more(PL_bufptr)) {
PL_lex_state = LEX_INTERPCONCAT;
return ')';
}
+ if (PL_lex_inwhat == OP_SUBST && 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
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);
retry:
switch (*s) {
default:
- /*
- * 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. You will see this not just here but throughout this file.
- */
- if (UTF && (*s & 0xc0) == 0x80) {
- if (isIDFIRST_utf8((U8*)s))
- goto keylookup;
- }
+ if (isIDFIRST_lazy(s))
+ goto keylookup;
croak("Unrecognized character \\x%02X", *s & 255);
case 4:
case 26:
else
newargv = PL_origargv;
newargv[0] = ipath;
- execv(ipath, newargv);
+ PerlProc_execv(ipath, newargv);
croak("Can't exec %s", ipath);
}
if (d) {
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':
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 {
else if (*s == '>') {
s++;
s = skipspace(s);
- if (isIDFIRST(*s)) {
+ if (isIDFIRST_lazy(s)) {
s = force_word(s,METHOD,FALSE,TRUE,FALSE);
TOKEN(ARROW);
}
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'))
}
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++;
|| (*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;
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;
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(';');
AOPERATOR(ANDAND);
s--;
if (PL_expect == XOPERATOR) {
- if (ckWARN(WARN_SEMICOLON) && isALPHA(*s) && PL_bufptr == PL_linestart) {
+ if (ckWARN(WARN_SEMICOLON) && isIDFIRST_lazy(s) && PL_bufptr == PL_linestart) {
PL_curcop->cop_line--;
- warner(WARN_SEMICOLON, warn_nosemi);
+ warner(WARN_SEMICOLON, PL_warn_nosemi);
PL_curcop->cop_line++;
}
BAop(OP_BIT_AND);
}
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;
}
}
- 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] = '@';
PL_tokenbuf[0] = '@';
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);
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))
+ for (; isSPACE(*t); t++) ;
+ if (*t == ';' && perl_get_cv(tmpbuf, FALSE))
warner(WARN_SYNTAX,
"You need to quote \"%s\"", tmpbuf);
}
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)) {
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 = '$';
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++;
/* 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());
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;
case 'z': case 'Z':
keylookup: {
+ STRLEN n_a;
gv = Nullgv;
gvp = 0;
if (PL_expect == XOPERATOR) {
if (PL_bufptr == PL_linestart) {
PL_curcop->cop_line--;
- warner(WARN_SEMICOLON, warn_nosemi);
+ warner(WARN_SEMICOLON, PL_warn_nosemi);
PL_curcop->cop_line++;
}
else
(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] == '*')) )
/* 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. */
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;
}
PL_expect = XOPERATOR;
force_next(WORD);
yylval.ival = 0;
+ PL_last_lop_op = OP_ENTERSUB;
TOKEN('&');
}
/* 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) */
/* 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;
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",
if (lastchar != '-') {
for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
if (!*d)
- warner(WARN_RESERVED, warn_reserved, PL_tokenbuf);
+ warner(WARN_RESERVED, PL_warn_reserved, PL_tokenbuf);
}
}
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);
TERM(sublex_start());
case KEY_map:
- LOP(OP_MAPSTART,XREF);
+ LOP(OP_MAPSTART, XREF);
case KEY_mkdir:
LOP(OP_MKDIR,XTERM);
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) {
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)",
s = scan_str(s);
if (!s)
missingterm((char*)0);
- if (ckWARN(WARN_SYNTAX) && 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 == ',') {
- warner(WARN_SYNTAX,
- "Possible attempt to separate words with commas");
- break;
- }
- if (*d == '#') {
- warner(WARN_SYNTAX,
- "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);
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");
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);
PL_lex_stuff = Nullsv;
}
- if (*SvPV(PL_subname,PL_na) == '?') {
+ if (*SvPV(PL_subname,n_a) == '?') {
sv_setpv(PL_subname,"__ANON__");
TOKEN(ANONSUB);
}
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++;
bool oldcatch = CATCH_GET;
SV **cvp;
SV *cv, *typesv;
- char buf[128];
if (!table) {
yyerror("%^H is not defined");
}
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;
POPSTACK;
if (!SvOK(res)) {
+ char buf[128];
sprintf(buf,"Call to &{$^H{%s}} did not return a defined value", key);
yyerror(buf);
}
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++;
*d++ = *s++;
*d++ = *s++;
}
- else if (UTF && (*s & 0xc0) == 0x80 && isALNUM_utf8((U8*)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);
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++;
*d++ = *s++;
*d++ = *s++;
}
- else if (UTF && (*s & 0xc0) == 0x80 && isALNUM_utf8((U8*)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);
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("\"$$<digit>\" to mean \"${$}<digit>\"");
- else
- return s;
+ return s;
}
if (*s == '{') {
bracket = s;
}
}
}
- if (isIDFIRST(*d) || (UTF && (*d & 0xc0) == 0x80 && isIDFIRST_utf8((U8*)d))) {
+ if (isIDFIRST_lazy(d)) {
d++;
if (UTF) {
e = s;
- while (e < send && (isALNUM(*e) || ((*e & 0xc0) == 0x80 && isALNUM_utf8((U8*)e)) || *e == ':')) {
+ while (e < send && isALNUM_lazy(e) || *e == ':') {
e += UTF8SKIP(e);
while (e < send && *e & 0x80 && is_utf8_mark((U8*)e))
e += UTF8SKIP(e);
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;
}
if (*d == '$' && d[1]) d++;
/* allow <Pkg'VALUE> or <Pkg::VALUE> */
- 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
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;
}
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,
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;
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] == '.')
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 */
/* 8 and 9 are not octal */
case '8': case '9':
- if (shift != 4)
+ if (shift == 3)
yyerror("Illegal octal digit");
+ else
+ if (shift == 1)
+ yyerror("Illegal binary digit");
/* 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("Illegal binary digit");
+ /* FALL THROUGH */
+
+ case '0': case '1':
b = *s++ & 15; /* ASCII digit -> value of digit */
goto digit;
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 */
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) {