static char ident_too_long[] = "Identifier too long";
static void restore_rsfp(pTHXo_ void *f);
-static void restore_expect(pTHXo_ void *e);
-static void restore_lex_expect(pTHXo_ void *e);
+
+#define XFAKEBRACK 128
+#define XENUMMASK 127
#define UTF (PL_hints & HINT_UTF8)
/*
* utf16-to-utf8-reversed.
*/
-#ifdef WIN32
+#ifdef PERL_CR_FILTER
+static void
+strip_return(SV *sv)
+{
+ register char *s = SvPVX(sv);
+ register char *e = s + SvCUR(sv);
+ /* outer loop optimized to do nothing if there are no CR-LFs */
+ while (s < e) {
+ if (*s++ == '\r' && *s == '\n') {
+ /* hit a CR-LF, need to copy the rest */
+ register char *d = s - 1;
+ *d++ = *s++;
+ while (s < e) {
+ if (*s == '\r' && s[1] == '\n')
+ s++;
+ *d++ = *s++;
+ }
+ SvCUR(sv) -= s - d;
+ return;
+ }
+ }
+}
STATIC I32
-S_win32_textfilter(pTHX_ int idx, SV *sv, int maxlen)
+S_cr_textfilter(pTHX_ int idx, SV *sv, int maxlen)
{
- I32 count = FILTER_READ(idx+1, sv, maxlen);
- if (count > 0 && !maxlen)
- win32_strip_return(sv);
- return count;
+ I32 count = FILTER_READ(idx+1, sv, maxlen);
+ if (count > 0 && !maxlen)
+ strip_return(sv);
+ return count;
}
#endif
SAVEI32(PL_lex_dojoin);
SAVEI32(PL_lex_brackets);
- SAVEI32(PL_lex_fakebrack);
SAVEI32(PL_lex_casemods);
SAVEI32(PL_lex_starts);
SAVEI32(PL_lex_state);
SAVEI32(PL_lex_defer);
SAVEI32(PL_sublex_info.sub_inwhat);
SAVESPTR(PL_lex_repl);
- SAVEDESTRUCTOR_X(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */
- SAVEDESTRUCTOR_X(restore_lex_expect, PL_tokenbuf + PL_expect);
+ SAVEINT(PL_expect);
+ SAVEINT(PL_lex_expect);
PL_lex_state = LEX_NORMAL;
PL_lex_defer = 0;
PL_expect = XSTATE;
PL_lex_brackets = 0;
- PL_lex_fakebrack = 0;
New(899, PL_lex_brackstack, 120, char);
New(899, PL_lex_casestack, 12, char);
SAVEFREEPV(PL_lex_brackstack);
*t = '\0';
if (t - s > 0)
CopFILE_set(PL_curcop, s);
- else
- CopFILE_set(PL_curcop, PL_origfilename);
*t = ch;
CopLINE_set(PL_curcop, atoi(n)-1);
}
*/
STATIC I32
-S_lop(pTHX_ I32 f, expectation x, char *s)
+S_lop(pTHX_ I32 f, int x, char *s)
{
dTHR;
yylval.ival = f;
s = skipspace(s);
- /* default VERSION number -- GBARR */
-
- if(isDIGIT(*s)) {
- char *d;
- int c;
- for( d=s, c = 1; isDIGIT(*d) || *d == '_' || (*d == '.' && c--); d++);
- if((*d == ';' || isSPACE(*d)) && *(skipspace(d)) != ',') {
+ if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
+ char *d = s;
+ if (*d == 'v')
+ d++;
+ for (; isDIGIT(*d) || *d == '_' || *d == '.'; d++);
+ if ((*d == ';' || isSPACE(*d)) && *(skipspace(d)) != ',') {
s = scan_num(s);
/* real VERSION number -- GBARR */
version = yylval.opval;
PL_lex_state = PL_sublex_info.super_state;
SAVEI32(PL_lex_dojoin);
SAVEI32(PL_lex_brackets);
- SAVEI32(PL_lex_fakebrack);
SAVEI32(PL_lex_casemods);
SAVEI32(PL_lex_starts);
SAVEI32(PL_lex_state);
PL_lex_dojoin = FALSE;
PL_lex_brackets = 0;
- PL_lex_fakebrack = 0;
New(899, PL_lex_brackstack, 120, char);
New(899, PL_lex_casestack, 12, char);
SAVEFREEPV(PL_lex_brackstack);
SAVEFREESV(PL_linestr);
PL_lex_dojoin = FALSE;
PL_lex_brackets = 0;
- PL_lex_fakebrack = 0;
PL_lex_casemods = 0;
*PL_lex_casestack = '\0';
PL_lex_starts = 0;
if (ckWARN(WARN_UTF8))
Perl_warner(aTHX_ WARN_UTF8,
"\\x%.*s will produce malformed UTF-8 character; use \\x{%.*s} for that",
- len,s,len,s);
+ (int)len,s,(int)len,s);
}
*d++ = (char)uv;
}
STATIC char *
S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append)
{
-#ifdef WIN32FILTER
+#ifdef PERL_CR_FILTER
if (!PL_rsfp_filters) {
- filter_add(win32_textfilter,NULL);
+ filter_add(S_cr_textfilter,NULL);
}
#endif
if (PL_rsfp_filters) {
*/
if (PL_in_my) {
if (PL_in_my == KEY_our) { /* "our" is merely analogous to "my" */
+ if (strchr(PL_tokenbuf,':'))
+ yyerror(Perl_form(aTHX_ "No package name allowed for "
+ "variable %s in \"our\"",
+ PL_tokenbuf));
tmp = pad_allocmy(PL_tokenbuf);
}
else {
}
#endif /* USE_THREADS */
if ((tmp = pad_findmy(PL_tokenbuf)) != NOT_IN_PAD) {
+ SV *namesv = AvARRAY(PL_comppad_name)[tmp];
/* might be an "our" variable" */
- if (SvFLAGS(AvARRAY(PL_comppad_name)[tmp]) & SVpad_OUR) {
+ if (SvFLAGS(namesv) & SVpad_OUR) {
/* build ops for a bareword */
- yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf+1, 0));
+ SV *sym = newSVpv(HvNAME(GvSTASH(namesv)),0);
+ sv_catpvn(sym, "::", 2);
+ sv_catpv(sym, PL_tokenbuf+1);
+ yylval.opval = (OP*)newSVOP(OP_CONST, 0, sym);
yylval.opval->op_private = OPpCONST_ENTERED;
- gv_fetchpv(PL_tokenbuf+1,
+ gv_fetchpv(SvPVX(sym),
(PL_in_eval
- ? (GV_ADDMULTI | GV_ADDINEVAL | GV_ADDOUR)
- : GV_ADDOUR
+ ? (GV_ADDMULTI | GV_ADDINEVAL)
+ : TRUE
),
((PL_tokenbuf[0] == '$') ? SVt_PV
: (PL_tokenbuf[0] == '@') ? SVt_PVAV
attrs = Nullop;
while (isIDFIRST_lazy(s)) {
d = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, FALSE, &len);
+ if (isLOWER(*s) && (tmp = keyword(PL_tokenbuf, len))) {
+ if (tmp < 0) tmp = -tmp;
+ switch (tmp) {
+ case KEY_or:
+ case KEY_and:
+ case KEY_for:
+ case KEY_unless:
+ case KEY_if:
+ case KEY_while:
+ case KEY_until:
+ goto got_attrs;
+ default:
+ break;
+ }
+ }
if (*d == '(') {
d = scan_str(d,TRUE,TRUE);
if (!d) {
newSVpvn(s, len)));
}
s = skipspace(d);
- while (*s == ',')
+ if (*s == ':' && s[1] != ':')
s = skipspace(s+1);
+ else if (s == d)
+ break; /* require real whitespace or :'s */
}
- tmp = (PL_expect == XOPERATOR ? '=' : '{'); /*'}' for vi */
- if (*s != ';' && *s != tmp) {
+ tmp = (PL_expect == XOPERATOR ? '=' : '{'); /*'}(' for vi */
+ if (*s != ';' && *s != tmp && (tmp != '=' || *s != ')')) {
char q = ((*s == '\'') ? '"' : '\'');
/* If here for an expression, and parsed no attrs, back off. */
if (tmp == '=' && !attrs) {
op_free(attrs);
OPERATOR(':');
}
+ got_attrs:
if (attrs) {
PL_nextval[PL_nexttoke].opval = attrs;
force_next(THING);
if (++t < PL_bufend
&& (!isALNUM(*t)
|| ((*t == 'q' || *t == 'x') && ++t < PL_bufend
- && !isALNUM(*t)))) {
+ && !isALNUM(*t))))
+ {
char *tmps;
char open, close, term;
I32 brackets = 1;
}
t++;
}
- else if (isIDFIRST_lazy(s)) {
- for (t++; t < PL_bufend && isALNUM_lazy(t); t++) ;
+ else if (isALNUM_lazy(t)) {
+ t += UTF8SKIP(t);
+ while (t < PL_bufend && isALNUM_lazy(t))
+ t += UTF8SKIP(t);
}
while (t < PL_bufend && isSPACE(*t))
t++;
PL_lex_formbrack = 0;
if (PL_lex_state == LEX_INTERPNORMAL) {
if (PL_lex_brackets == 0) {
- if (PL_lex_fakebrack) {
+ if (PL_expect & XFAKEBRACK) {
+ PL_expect &= XENUMMASK;
PL_lex_state = LEX_INTERPEND;
PL_bufptr = s;
return yylex(); /* ignore fake brackets */
PL_lex_state = LEX_INTERPEND;
}
}
- if (PL_lex_brackets < PL_lex_fakebrack) {
+ if (PL_expect & XFAKEBRACK) {
+ PL_expect &= XENUMMASK;
PL_bufptr = s;
- PL_lex_fakebrack = 0;
return yylex(); /* ignore fake brackets */
}
force_next('}');
no_op("Backslash",s);
OPERATOR(REFGEN);
+ case 'v':
+ if (isDIGIT(s[1]) && PL_expect == XTERM) {
+ char *start = s;
+ start++;
+ start++;
+ while (isDIGIT(*start))
+ start++;
+ if (*start == '.' && isDIGIT(start[1])) {
+ s = scan_num(s);
+ TERM(THING);
+ }
+ }
+ goto keylookup;
case 'x':
if (isDIGIT(s[1]) && PL_expect == XOPERATOR) {
s++;
case 's': case 'S':
case 't': case 'T':
case 'u': case 'U':
- case 'v': case 'V':
+ case 'V':
case 'w': case 'W':
case 'X':
case 'y': case 'Y':
IoTYPE(GvIOp(gv)) = '-';
else
IoTYPE(GvIOp(gv)) = '<';
+#if defined(WIN32) && !defined(PERL_TEXTMODE_SCRIPTS)
+ /* if the script was opened in binmode, we need to revert
+ * it to text mode for compatibility; but only iff it has CRs
+ * XXX this is a questionable hack at best. */
+ if (PL_bufend-PL_bufptr > 2
+ && PL_bufend[-1] == '\n' && PL_bufend[-2] == '\r')
+ {
+ Off_t loc = 0;
+ if (IoTYPE(GvIOp(gv)) == '<') {
+ loc = PerlIO_tell(PL_rsfp);
+ (void)PerlIO_seek(PL_rsfp, 0L, 0);
+ }
+ if (PerlLIO_setmode(PerlIO_fileno(PL_rsfp), O_TEXT) != -1) {
+#if defined(__BORLANDC__)
+ /* XXX see note in do_binmode() */
+ ((FILE*)PL_rsfp)->flags |= _F_BIN;
+#endif
+ if (loc > 0)
+ PerlIO_seek(PL_rsfp, loc, 0);
+ }
+ }
+#endif
PL_rsfp = Nullfp;
}
goto fake_eof;
case KEY_AUTOLOAD:
case KEY_DESTROY:
case KEY_BEGIN:
- case KEY_END:
- case KEY_STOP:
+ case KEY_CHECK:
case KEY_INIT:
+ case KEY_END:
if (PL_expect == XSTATE) {
s = PL_bufptr;
goto really_sub;
Rop(OP_SGE);
case KEY_grep:
- LOP(OP_GREPSTART, *s == '(' ? XTERM : XREF);
+ LOP(OP_GREPSTART, XREF);
case KEY_goto:
s = force_word(s,WORD,TRUE,FALSE,FALSE);
TERM(sublex_start());
case KEY_map:
- LOP(OP_MAPSTART, *s == '(' ? XTERM : XREF);
+ LOP(OP_MAPSTART, XREF);
case KEY_mkdir:
LOP(OP_MKDIR,XTERM);
OLDLOP(OP_RETURN);
case KEY_require:
- *PL_tokenbuf = '\0';
- s = force_word(s,WORD,TRUE,TRUE,FALSE);
- if (isIDFIRST_lazy(PL_tokenbuf))
- gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE);
- else if (*s == '<')
- yyerror("<> should be quotes");
+ s = skipspace(s);
+ if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
+ s = force_version(s);
+ }
+ else {
+ *PL_tokenbuf = '\0';
+ s = force_word(s,WORD,TRUE,TRUE,FALSE);
+ if (isIDFIRST_lazy(PL_tokenbuf))
+ gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE);
+ else if (*s == '<')
+ yyerror("<> should be quotes");
+ }
UNI(OP_REQUIRE);
case KEY_reset:
if (PL_expect != XSTATE)
yyerror("\"use\" not allowed in expression");
s = skipspace(s);
- if(isDIGIT(*s)) {
+ if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
s = force_version(s);
- if(*s == ';' || (s = skipspace(s), *s == ';')) {
+ if (*s == ';' || (s = skipspace(s), *s == ';')) {
PL_nextval[PL_nexttoke].opval = Nullop;
force_next(WORD);
}
break;
case 'C':
if (strEQ(d,"CORE")) return -KEY_CORE;
+ if (strEQ(d,"CHECK")) return KEY_CHECK;
break;
case 'c':
switch (len) {
break;
}
break;
- case 'S':
- if (strEQ(d,"STOP")) return KEY_STOP;
- break;
case 's':
switch (d[1]) {
case 0: return KEY_s;
char *bracket = 0;
char funny = *s++;
- if (PL_lex_brackets == 0)
- PL_lex_fakebrack = 0;
if (isSPACE(*s))
s = skipspace(s);
d = dest;
"Ambiguous use of %c{%s%s} resolved to %c%s%s",
funny, dest, brack, funny, dest, brack);
}
- PL_lex_fakebrack = PL_lex_brackets+1;
bracket++;
- PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
+ PL_lex_brackstack[PL_lex_brackets++] = (char)(XOPERATOR | XFAKEBRACK);
return s;
}
}
register char *e; /* end of temp buffer */
IV tryiv; /* used to see if it can be an IV */
NV value; /* number read, as a double */
- SV *sv; /* place to put the converted number */
+ SV *sv = Nullsv; /* place to put the converted number */
bool floatit; /* boolean: int or float? */
char *lastub = 0; /* position of last underbar */
static char number_too_long[] = "Number too long";
Perl_croak(aTHX_ "panic: scan_num");
/* if it starts with a 0, it could be an octal number, a decimal in
- 0.13 disguise, or a hexadecimal number, or a binary number.
- */
+ 0.13 disguise, or a hexadecimal number, or a binary number. */
case '0':
{
/* variables:
(floatit ? "float" : "integer"),
sv, Nullsv, NULL);
break;
+ /* if it starts with a v, it could be a version number */
+ case 'v':
+ {
+ char *pos = s;
+ pos++;
+ while (isDIGIT(*pos))
+ pos++;
+ if (*pos == '.' && isDIGIT(pos[1])) {
+ UV rev;
+ U8 tmpbuf[10];
+ U8 *tmpend;
+ NV nshift = 1.0;
+ s++; /* get past 'v' */
+
+ sv = NEWSV(92,5);
+ SvUPGRADE(sv, SVt_PVNV);
+ sv_setpvn(sv, "", 0);
+
+ do {
+ rev = atoi(s);
+ s = ++pos;
+ while (isDIGIT(*pos))
+ pos++;
+
+ tmpend = uv_to_utf8(tmpbuf, rev);
+ *tmpend = '\0';
+ sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
+ if (rev > 0)
+ SvNVX(sv) += (NV)rev/nshift;
+ nshift *= 1000;
+ } while (*pos == '.' && isDIGIT(pos[1]));
+
+ rev = atoi(s);
+ s = pos;
+ tmpend = uv_to_utf8(tmpbuf, rev);
+ *tmpend = '\0';
+ sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
+ if (rev > 0)
+ SvNVX(sv) += (NV)rev/nshift;
+
+ SvPOK_on(sv);
+ SvNOK_on(sv);
+ SvREADONLY_on(sv);
+ SvUTF8_on(sv);
+ }
+ }
+ break;
}
/* make the op for the constant and return */
- yylval.opval = newSVOP(OP_CONST, 0, sv);
+ if (sv)
+ yylval.opval = newSVOP(OP_CONST, 0, sv);
+ else
+ yylval.opval = Nullop;
return s;
}
needargs = TRUE;
}
sv_catpvn(stuff, s, eol-s);
+#ifndef PERL_STRICT_CR
+ if (eol-s > 1 && eol[-2] == '\r' && eol[-1] == '\n') {
+ char *end = SvPVX(stuff) + SvCUR(stuff);
+ end[-2] = '\n';
+ end[-1] = '\0';
+ SvCUR(stuff)--;
+ }
+#endif
}
s = eol;
if (PL_rsfp) {
PL_multi_end = 0;
}
if (PL_in_eval & EVAL_WARNONLY)
- Perl_warn(aTHX_ "%_", msg);
+ Perl_warn(aTHX_ "%"SVf, msg);
else
qerror(msg);
if (PL_error_count >= 10)
PerlIO_close(PL_rsfp);
PL_rsfp = fp;
}
-
-/*
- * restore_expect
- * Restores the state of PL_expect when the lexing that begun with a
- * start_lex() call has ended.
- */
-
-static void
-restore_expect(pTHXo_ void *e)
-{
- /* a safe way to store a small integer in a pointer */
- PL_expect = (expectation)((char *)e - PL_tokenbuf);
-}
-
-/*
- * restore_lex_expect
- * Restores the state of PL_lex_expect when the lexing that begun with a
- * start_lex() call has ended.
- */
-
-static void
-restore_lex_expect(pTHXo_ void *e)
-{
- /* a safe way to store a small integer in a pointer */
- PL_lex_expect = (expectation)((char *)e - PL_tokenbuf);
-}