/* 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.
? 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).
*/
#ifdef USE_PURE_BISON
YYSTYPE* yylval_pointer = NULL;
int* yychar_pointer = NULL;
-# ifdef EMBED
-# undef yylval
-# undef yychar
-# endif
+# undef yylval
+# undef yychar
# define yylval (*yylval_pointer)
# define yychar (*yychar_pointer)
# define PERL_YYLEX_PARAM yylval_pointer,yychar_pointer
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;
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;
}
}
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;
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));
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] == '\\'))
SV *nsv;
p = SvPV(sv, len);
- nsv = newSVpv(p, len);
+ nsv = newSVpvn(p, len);
SvREFCNT_dec(sv);
sv = nsv;
}
{
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;
}
PL_lex_casemods = 0;
*PL_lex_casestack = '\0';
PL_lex_starts = 0;
- if (SvCOMPILED(PL_lex_repl)) {
+ if (SvEVALED(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 {
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
+ 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
+ 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;
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':
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);
* 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))) == (DIR*)funcp){
+ IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) = NULL;
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 */
*/
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);
PL_lex_state = LEX_INTERPCONCAT;
return ')';
}
+ if (PL_lex_inwhat == OP_SUBST && PL_linestr == PL_lex_repl
+ && SvEVALED(PL_lex_repl))
+ {
+ if (PL_bufptr != PL_bufend)
+ croak("Bad evalled substitution pattern");
+ PL_lex_repl = Nullsv;
+ }
/* FALLTHROUGH */
case LEX_INTERPCONCAT:
#ifdef DEBUGGING
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)
else
newargv = PL_origargv;
newargv[0] = ipath;
- execv(ipath, newargv);
+ PerlProc_execv(ipath, newargv);
croak("Can't exec %s", ipath);
}
if (d) {
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) {
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)
if (PL_expect == XOPERATOR) {
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);
}
d = s;
+ tmp = (I32)*s;
if (PL_lex_state == LEX_NORMAL)
s = skipspace(s);
}
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;
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
/* 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
PL_oldoldbufptr < PL_bufptr &&
(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_last_lop_op == OP_ENTERSUB
- && PL_last_proto
- && PL_last_proto[PL_last_proto[0] == ';' ? 1 : 0] == '*')) )
+ (PL_expect == XREF ||
+ ((PL_opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF))
{
bool immediate_paren = *s == '(';
/* (But it's an indir obj regardless for sort.) */
if ((PL_last_lop_op == OP_SORT ||
- (!immediate_paren && (!gv || !GvCVu(gv))) ) &&
- (PL_last_lop_op != OP_MAPSTART && PL_last_lop_op != OP_GREPSTART)){
+ (!immediate_paren && (!gv || !GvCVu(gv)))) &&
+ (PL_last_lop_op != OP_MAPSTART &&
+ PL_last_lop_op != OP_GREPSTART))
+ {
PL_expect = (PL_last_lop == PL_oldoldbufptr) ? XTERM : XOPERATOR;
goto bareword;
}
if (*s == '(') {
CLINE;
if (gv && GvCVu(gv)) {
- CV *cv;
- if ((cv = GvCV(gv)) && SvPOK(cv))
- PL_last_proto = SvPV((SV*)cv, PL_na);
for (d = s + 1; *d == ' ' || *d == '\t'; d++) ;
- if (*d == ')' && (sv = cv_const_sv(cv))) {
+ if (*d == ')' && (sv = cv_const_sv(GvCV(gv)))) {
s = d + 1;
goto its_constant;
}
PL_expect = XOPERATOR;
force_next(WORD);
yylval.ival = 0;
- PL_last_lop_op = OP_ENTERSUB;
TOKEN('&');
}
if (lastchar == '-')
warn("Ambiguous use of -%s resolved as -&%s()",
PL_tokenbuf, PL_tokenbuf);
- PL_last_lop = PL_oldbufptr;
- PL_last_lop_op = OP_ENTERSUB;
/* Check for a constant sub */
cv = GvCV(gv);
if ((sv = cv_const_sv(cv))) {
/* Resolve to GV now. */
op_free(yylval.opval);
yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
+ yylval.opval->op_private |= OPpENTERSUB_NOPAREN;
+ PL_last_lop = PL_oldbufptr;
PL_last_lop_op = OP_ENTERSUB;
/* Is there a prototype? */
if (SvPOK(cv)) {
STRLEN len;
- PL_last_proto = SvPV((SV*)cv, len);
+ char *proto = SvPV((SV*)cv, len);
if (!len)
TERM(FUNC0SUB);
- if (strEQ(PL_last_proto, "$"))
+ if (strEQ(proto, "$"))
OPERATOR(UNIOPSUB);
- if (*PL_last_proto == '&' && *s == '{') {
+ if (*proto == '&' && *s == '{') {
sv_setpv(PL_subname,"__ANON__");
PREBLOCK(LSTOPSUB);
}
- } else
- PL_last_proto = NULL;
+ }
PL_nextval[PL_nexttoke].opval = yylval.opval;
PL_expect = XTERM;
force_next(WORD);
TOKEN(NOAMP);
}
- if (PL_hints & HINT_STRICT_SUBS &&
- lastchar != '-' &&
- strnNE(s,"->",2) &&
- 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_ENTERSUB
- && PL_last_proto
- && PL_last_proto[PL_last_proto[0] == ';' ? 1 : 0] == '*'))
- {
- warn(
- "Bareword \"%s\" not allowed while \"strict subs\" in use",
- PL_tokenbuf);
- ++PL_error_count;
- }
-
/* Call it a bare word */
- bareword:
- if (ckWARN(WARN_RESERVED)) {
- if (lastchar != '-') {
- for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
- if (!*d)
- warner(WARN_RESERVED, warn_reserved, PL_tokenbuf);
+ if (PL_hints & HINT_STRICT_SUBS)
+ yylval.opval->op_private |= OPpCONST_STRICT;
+ else {
+ bareword:
+ if (ckWARN(WARN_RESERVED)) {
+ if (lastchar != '-') {
+ for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
+ if (!*d)
+ warner(WARN_RESERVED, PL_warn_reserved,
+ PL_tokenbuf);
+ }
}
}
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);
PL_lex_stuff = Nullsv;
}
- if (*SvPV(PL_subname,PL_na) == '?') {
+ if (*SvPV(PL_subname,n_a) == '?') {
sv_setpv(PL_subname,"__ANON__");
TOKEN(ANONSUB);
}
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;
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
POPSTACK;
if (!SvOK(res)) {
+ char buf[128];
sprintf(buf,"Call to &{$^H{%s}} did not return a defined value", key);
yyerror(buf);
}
if (s < send)
*d = *s++;
d[1] = '\0';
- if (*d == '^' && *s && (isUPPER(*s) || strchr("[\\]^_?", *s))) {
+ if (*d == '^' && *s && isCONTROLVAR(*s)) {
*d = toCTRL(*s);
s++;
}
s = e;
}
else {
- while (isALNUM(*s) || *s == ':')
+ while ((isALNUM(*s) || *s == ':') && d < e)
*d++ = *s++;
+ if (d >= e)
+ croak(ident_too_long);
}
*d = '\0';
while (s < send && (*s == ' ' || *s == '\t')) s++;
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++;
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);
sv_catsv(repl, PL_lex_repl);
sv_catpvn(repl, " };", 2);
- SvCOMPILED_on(repl);
+ SvEVALED_on(repl);
SvREFCNT_dec(PL_lex_repl);
PL_lex_repl = repl;
}
#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);
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)) ) {
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);
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++;
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)
- 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;
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 */
dTHR;
register char *eol;
register char *t;
- SV *stuff = newSVpv("",0);
+ SV *stuff = newSVpvn("",0);
bool needargs = FALSE;
while (!needargs) {
#else
for (t = s+1;*t == ' ' || *t == '\t' || *t == '\r'; t++) ;
#endif
- if (*t == '\n')
+ if (*t == '\n' || t == PL_bufend)
break;
}
if (PL_in_eval && !PL_rsfp) {
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 */
{
dTHR;
--PL_error_count;
- PL_in_eval |= 2;
+ PL_in_eval |= EVAL_WARNONLY;
yyerror(s);
- PL_in_eval &= ~2;
+ PL_in_eval &= ~EVAL_WARNONLY;
return 0;
}
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))
(int)PL_multi_open,(int)PL_multi_close,(long)PL_multi_start);
PL_multi_end = 0;
}
- if (PL_in_eval & 2)
+ if (PL_in_eval & EVAL_WARNONLY)
warn("%_", msg);
else if (PL_in_eval)
sv_catsv(ERRSV, msg);