summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorMalcolm Beattie <mbeattie@sable.ox.ac.uk>1997-10-08 10:19:27 +0000
committerMalcolm Beattie <mbeattie@sable.ox.ac.uk>1997-10-08 10:19:27 +0000
commit93af7a870f71dbbb13443b4087703de0221add17 (patch)
treee767c53d4d4f1783640e5410f94655e45b58b3d0 /toke.c
parentc116a00cf797ec2e6795338ee18b88d975e760c5 (diff)
parent2269e8ecc334a5a77bdb915666547431c0171402 (diff)
downloadperl-93af7a870f71dbbb13443b4087703de0221add17.tar.gz
Merge maint-5.004 branch (5.004_03) with mainline.
MANIFEST is out of sync. p4raw-id: //depot/perl@114
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c132
1 files changed, 106 insertions, 26 deletions
diff --git a/toke.c b/toke.c
index 78ae386967..408760ce49 100644
--- a/toke.c
+++ b/toke.c
@@ -372,7 +372,9 @@ register char *s;
return s;
if ((s = filter_gets(linestr, rsfp, (prevlen = SvCUR(linestr)))) == Nullch) {
if (minus_n || minus_p) {
- sv_setpv(linestr,minus_p ? ";}continue{print" : "");
+ sv_setpv(linestr,minus_p ?
+ ";}continue{print or die qq(-p destination: $!\\n)" :
+ "");
sv_catpv(linestr,";}");
minus_n = minus_p = 0;
}
@@ -386,6 +388,8 @@ register char *s;
PerlIO_clearerr(rsfp);
else
(void)PerlIO_close(rsfp);
+ if (e_fp == rsfp)
+ e_fp = Nullfp;
rsfp = Nullfp;
return s;
}
@@ -393,7 +397,7 @@ register char *s;
bufend = s + SvCUR(linestr);
s = bufptr;
incline(s);
- if (perldb && curstash != debstash) {
+ if (PERLDB_LINE && curstash != debstash) {
SV *sv = NEWSV(85,0);
sv_upgrade(sv, SVt_PVMG);
@@ -1532,7 +1536,7 @@ yylex()
sv_catpv(linestr, "\n");
oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
bufend = SvPVX(linestr) + SvCUR(linestr);
- if (perldb && curstash != debstash) {
+ if (PERLDB_LINE && curstash != debstash) {
SV *sv = NEWSV(85,0);
sv_upgrade(sv, SVt_PVMG);
@@ -1551,6 +1555,8 @@ yylex()
PerlIO_clearerr(rsfp);
else
(void)PerlIO_close(rsfp);
+ if (e_fp == rsfp)
+ e_fp = Nullfp;
rsfp = Nullfp;
}
if (!in_eval && (minus_n || minus_p)) {
@@ -1580,7 +1586,7 @@ yylex()
incline(s);
} while (doextract);
oldoldbufptr = oldbufptr = bufptr = linestart = s;
- if (perldb && curstash != debstash) {
+ if (PERLDB_LINE && curstash != debstash) {
SV *sv = NEWSV(85,0);
sv_upgrade(sv, SVt_PVMG);
@@ -1705,7 +1711,7 @@ yylex()
}
d = moreswitches(d);
} while (d);
- if (perldb && !oldpdb ||
+ if (PERLDB_LINE && !oldpdb ||
( minus_n || minus_p ) && !(oldn || oldp) )
/* if we have already added "LINE: while (<>) {",
we must not do it again */
@@ -1714,7 +1720,7 @@ yylex()
oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
bufend = SvPVX(linestr) + SvCUR(linestr);
preambled = FALSE;
- if (perldb)
+ if (PERLDB_LINE)
(void)gv_fetchfile(origfilename);
goto retry;
}
@@ -1998,19 +2004,73 @@ yylex()
s = skipspace(s);
if (*s == '}')
OPERATOR(HASHBRACK);
- if (isALPHA(*s)) {
- for (t = s; t < bufend && isALNUM(*t); t++) ;
+ /* This hack serves to disambiguate a pair of curlies
+ * as being a block or an anon hash. Normally, expectation
+ * determines that, but in cases where we're not in a
+ * position to expect anything in particular (like inside
+ * eval"") we have to resolve the ambiguity. This code
+ * covers the case where the first term in the curlies is a
+ * quoted string. Most other cases need to be explicitly
+ * disambiguated by prepending a `+' before the opening
+ * curly in order to force resolution as an anon hash.
+ *
+ * XXX should probably propagate the outer expectation
+ * into eval"" to rely less on this hack, but that could
+ * potentially break current behavior of eval"".
+ * GSAR 97-07-21
+ */
+ t = s;
+ if (*s == '\'' || *s == '"' || *s == '`') {
+ /* common case: get past first string, handling escapes */
+ for (t++; t < bufend && *t != *s;)
+ if (*t++ == '\\' && (*t == '\\' || *t == *s))
+ t++;
+ t++;
}
- else if (*s == '\'' || *s == '"') {
- t = strchr(s+1,*s);
- if (!t++)
- t = s;
+ else if (*s == 'q') {
+ if (++t < bufend
+ && (!isALNUM(*t)
+ || ((*t == 'q' || *t == 'x') && ++t < bufend
+ && !isALNUM(*t)))) {
+ char *tmps;
+ char open, close, term;
+ I32 brackets = 1;
+
+ while (t < bufend && isSPACE(*t))
+ t++;
+ term = *t;
+ open = term;
+ if (term && (tmps = strchr("([{< )]}> )]}>",term)))
+ term = tmps[5];
+ close = term;
+ if (open == close)
+ for (t++; t < bufend; t++) {
+ if (*t == '\\' && t+1 < bufend && open != '\\')
+ t++;
+ else if (*t == open)
+ break;
+ }
+ else
+ for (t++; t < bufend; t++) {
+ if (*t == '\\' && t+1 < bufend)
+ t++;
+ else if (*t == close && --brackets <= 0)
+ break;
+ else if (*t == open)
+ brackets++;
+ }
+ }
+ t++;
+ }
+ else if (isALPHA(*s)) {
+ for (t++; t < bufend && isALNUM(*t); t++) ;
}
- else
- t = s;
while (t < bufend && isSPACE(*t))
t++;
- if ((*t == ',' && !isLOWER(*s)) || (*t == '=' && t[1] == '>'))
+ /* if comma follows first term, call it an anon hash */
+ /* XXX it could be a comma expression with loop modifiers */
+ if (t < bufend && ((*t == ',' && (*s == 'q' || !isLOWER(*s)))
+ || (*t == '=' && t[1] == '>')))
OPERATOR(HASHBRACK);
if (expect == XREF)
expect = XTERM;
@@ -2268,8 +2328,23 @@ yylex()
else if (isIDFIRST(*s)) {
char tmpbuf[sizeof tokenbuf];
scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len);
- if (keyword(tmpbuf, len))
- expect = XTERM; /* e.g. print $fh length() */
+ if (tmp = keyword(tmpbuf, len)) {
+ /* binary operators exclude handle interpretations */
+ switch (tmp) {
+ case -KEY_x:
+ case -KEY_eq:
+ case -KEY_ne:
+ case -KEY_gt:
+ case -KEY_lt:
+ case -KEY_ge:
+ case -KEY_le:
+ case -KEY_cmp:
+ break;
+ default:
+ expect = XTERM; /* e.g. print $fh length() */
+ break;
+ }
+ }
else {
GV *gv = gv_fetchpv(tmpbuf, FALSE, SVt_PVCV);
if (gv && GvCVu(gv))
@@ -4320,7 +4395,7 @@ char *what;
}
if (*w)
for (; *w && isSPACE(*w); w++) ;
- if (!*w || !strchr(";|})]oa!=", *w)) /* an advisory hack only... */
+ if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */
warn("%s (...) interpreted as function",name);
}
while (s < bufend && isSPACE(*s))
@@ -4486,7 +4561,7 @@ I32 ck_uni;
lex_state = LEX_INTERPEND;
if (funny == '#')
funny = '@';
- if (dowarn &&
+ if (dowarn && 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);
@@ -4804,7 +4879,7 @@ register char *s;
missingterm(tokenbuf);
}
curcop->cop_line++;
- if (perldb && curstash != debstash) {
+ if (PERLDB_LINE && curstash != debstash) {
SV *sv = NEWSV(88,0);
sv_upgrade(sv, SVt_PVMG);
@@ -4905,8 +4980,13 @@ char *start;
register char *to;
I32 brackets = 1;
- if (isSPACE(*s))
- s = skipspace(s);
+ if (isSPACE(*s)) {
+ /* "#" is allowed as delimiter if on same line */
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (isSPACE(*s))
+ s = skipspace(s);
+ }
CLINE;
term = *s;
multi_start = curcop->cop_line;
@@ -4942,13 +5022,13 @@ char *start;
for (; s < bufend; s++,to++) {
if (*s == '\n' && !rsfp)
curcop->cop_line++;
- if (*s == '\\' && s+1 < bufend && term != '\\') {
- if (s[1] == term)
+ if (*s == '\\' && s+1 < bufend) {
+ if ((s[1] == multi_open) || (s[1] == multi_close))
s++;
else
*to++ = *s++;
}
- else if (*s == term && --brackets <= 0)
+ else if (*s == multi_close && --brackets <= 0)
break;
else if (*s == multi_open)
brackets++;
@@ -4967,7 +5047,7 @@ char *start;
return Nullch;
}
curcop->cop_line++;
- if (perldb && curstash != debstash) {
+ if (PERLDB_LINE && curstash != debstash) {
SV *sv = NEWSV(88,0);
sv_upgrade(sv, SVt_PVMG);