* "It all comes from here, the stench and the peril." --Frodo
*/
-/* toke.c
- *
- * This file is the tokenizer for Perl. It's closely linked to the
+/*
+ * This file is the lexer for Perl. It's closely linked to the
* parser, perly.y.
*
* The main routine is yylex(), which returns the next token.
* 1999-02-27 mjd-perl-patch@plover.com */
#define isCONTROLVAR(x) (isUPPER(x) || strchr("[\\]^_?", (x)))
+/* On MacOS, respect nonbreaking spaces */
+#ifdef MACOS_TRADITIONAL
+#define SPACE_OR_TAB(c) ((c)==' '||(c)=='\312'||(c)=='\t')
+#else
+#define SPACE_OR_TAB(c) ((c)==' '||(c)=='\t')
+#endif
+
/* LEX_* are values for PL_lex_state, the state of the lexer.
* They are arranged oddly so that the guard on the switch statement
* can get by with a single comparison (if the compiler is smart enough).
/*
* Convenience functions to return different tokens and prime the
- * tokenizer for the next token. They all take an argument.
+ * lexer for the next token. They all take an argument.
*
* TOKEN : generic token (used for '(', DOLSHARP, etc)
* OPERATOR : generic operator
* LOOPX : loop exiting command (goto, last, dump, etc)
* FTST : file test operator
* FUN0 : zero-argument function
- * FUN1 : not used
+ * FUN1 : not used, except for not, which isn't a UNIOP
* BOop : bitwise or or xor
* BAop : bitwise and
* SHop : shift operator
* PWop : power operator
- * PMop : matching operator
+ * PMop : pattern-matching operator
* Aop : addition-level operator
* Mop : multiplication-level operator
* Eop : equality-testing operator
char *oldbp = PL_bufptr;
bool is_first = (PL_oldbufptr == PL_linestart);
- assert(s >= oldbp);
- PL_bufptr = s;
+ if (!s)
+ s = oldbp;
+ else {
+ assert(s >= oldbp);
+ PL_bufptr = s;
+ }
yywarn(Perl_form(aTHX_ "%s found where operator expected", what));
if (is_first)
Perl_warn(aTHX_ "\t(Missing semicolon on previous line?)\n");
/*
* Perl_deprecate
- * Warns that something is deprecated. Duh.
*/
void
/*
* depcom
- * Deprecate a comma-less variable list. Called from three places
- * in the tokenizer.
+ * Deprecate a comma-less variable list.
*/
STATIC void
}
/*
- * text filters for win32 carriage-returns, utf16-to-utf8 and
- * utf16-to-utf8-reversed, whatever that is.
+ * experimental text filters for win32 carriage-returns, utf16-to-utf8 and
+ * utf16-to-utf8-reversed.
*/
#ifdef WIN32
/*
* Perl_lex_start
- * Initialize variables. Called by perl.c. It uses the Perl stack
- * to save its state (for recursive calls to the parser).
+ * Initialize variables. Uses the Perl save_stack to save its state (for
+ * recursive calls to the parser).
*/
void
SAVESPTR(PL_linestr);
SAVEPPTR(PL_lex_brackstack);
SAVEPPTR(PL_lex_casestack);
- SAVEDESTRUCTOR(restore_rsfp, PL_rsfp);
+ SAVEDESTRUCTOR_X(restore_rsfp, PL_rsfp);
SAVESPTR(PL_lex_stuff);
SAVEI32(PL_lex_defer);
+ SAVEI32(PL_sublex_info.sub_inwhat);
SAVESPTR(PL_lex_repl);
- SAVEDESTRUCTOR(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */
- SAVEDESTRUCTOR(restore_lex_expect, PL_tokenbuf + PL_expect);
+ SAVEDESTRUCTOR_X(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */
+ SAVEDESTRUCTOR_X(restore_lex_expect, PL_tokenbuf + PL_expect);
PL_lex_state = LEX_NORMAL;
PL_lex_defer = 0;
PL_lex_repl = Nullsv;
PL_lex_inpat = 0;
PL_lex_inwhat = 0;
+ PL_sublex_info.sub_inwhat = 0;
PL_linestr = line;
if (SvREADONLY(PL_linestr))
PL_linestr = sv_2mortal(newSVsv(PL_linestr));
/*
* Perl_lex_end
- * Tidy up. Called from pp_ctl.c in the sv_compile_2op(), doeval(),
- * and pp_leaveeval() subroutines.
+ * Finalizer for lexing operations. Must be called when the parser is
+ * done with the lexer.
*/
void
* or pinball tables. Its name is short for "increment line". It
* increments the current line number in PL_curcop->cop_line and checks
* to see whether the line starts with a comment of the form
- * # line 500
- * If so, it sets the current line number to the number in the comment.
+ * # line 500 "foo.pm"
+ * If so, it sets the current line number and file to the values in the comment.
*/
STATIC void
char ch;
int sawline = 0;
+ PERL_ASYNC_CHECK();
PL_curcop->cop_line++;
if (*s++ != '#')
return;
- while (*s == ' ' || *s == '\t') s++;
+ while (SPACE_OR_TAB(*s)) s++;
if (strnEQ(s, "line ", 5)) {
s += 5;
sawline = 1;
n = s;
while (isDIGIT(*s))
s++;
- while (*s == ' ' || *s == '\t')
+ while (SPACE_OR_TAB(*s))
s++;
if (*s == '"' && (t = strchr(s+1, '"')))
s++;
ch = *t;
*t = '\0';
if (t - s > 0)
- PL_curcop->cop_filegv = gv_fetchfile(s);
+ CopFILEGV_set(PL_curcop, gv_fetchfile(s));
else
- PL_curcop->cop_filegv = gv_fetchfile(PL_origfilename);
+ CopFILEGV_set(PL_curcop, gv_fetchfile(PL_origfilename));
*t = ch;
PL_curcop->cop_line = atoi(n)-1;
}
{
dTHR;
if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
- while (s < PL_bufend && (*s == ' ' || *s == '\t'))
+ while (s < PL_bufend && SPACE_OR_TAB(*s))
s++;
return s;
}
for (;;) {
STRLEN prevlen;
+ SSize_t oldprevlen, oldoldprevlen;
+ SSize_t oldloplen, oldunilen;
while (s < PL_bufend && isSPACE(*s)) {
if (*s++ == '\n' && PL_in_eval && !PL_rsfp)
incline(s);
* of the buffer, we're not reading from a source filter, and
* we're in normal lexing mode
*/
- if (s < PL_bufend || !PL_rsfp || PL_lex_state != LEX_NORMAL)
+ if (s < PL_bufend || !PL_rsfp || PL_sublex_info.sub_inwhat ||
+ PL_lex_state == LEX_FORMLINE)
return s;
/* try to recharge the buffer */
- if ((s = filter_gets(PL_linestr, PL_rsfp, (prevlen = SvCUR(PL_linestr)))) == Nullch) {
- /* end of file. Add on the -p or -n magic */
+ if ((s = filter_gets(PL_linestr, PL_rsfp,
+ (prevlen = SvCUR(PL_linestr)))) == Nullch)
+ {
+ /* end of file. Add on the -p or -n magic */
if (PL_minus_n || PL_minus_p) {
sv_setpv(PL_linestr,PL_minus_p ?
";}continue{print or die qq(-p destination: $!\\n)" :
sv_setpv(PL_linestr,";");
/* reset variables for next time we lex */
- PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = s = PL_linestart = SvPVX(PL_linestr);
+ PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = s = PL_linestart
+ = SvPVX(PL_linestr);
PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
/* Close the filehandle. Could be from -P preprocessor,
}
/* not at end of file, so we only read another line */
+ /* make corresponding updates to old pointers, for yyerror() */
+ oldprevlen = PL_oldbufptr - PL_bufend;
+ oldoldprevlen = PL_oldoldbufptr - PL_bufend;
+ if (PL_last_uni)
+ oldunilen = PL_last_uni - PL_bufend;
+ if (PL_last_lop)
+ oldloplen = PL_last_lop - PL_bufend;
PL_linestart = PL_bufptr = s + prevlen;
PL_bufend = s + SvCUR(PL_linestr);
s = PL_bufptr;
+ PL_oldbufptr = s + oldprevlen;
+ PL_oldoldbufptr = s + oldoldprevlen;
+ if (PL_last_uni)
+ PL_last_uni = s + oldunilen;
+ if (PL_last_lop)
+ PL_last_lop = s + oldloplen;
incline(s);
/* debugger active and we're not compiling the debugger code,
sv_upgrade(sv, SVt_PVMG);
sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
- av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
+ av_store(CopFILEAV(PL_curcop),(I32)PL_curcop->cop_line,sv);
}
}
}
/*
* S_force_next
- * When the tokenizer realizes it knows the next token (for instance,
+ * When the lexer realizes it knows the next token (for instance,
* it is reordering tokens for the parser) then it can call S_force_next
- * to make the current token be the next one. It will also set
- * PL_nextval, and possibly PL_expect to ensure the lexer handles the
- * token correctly.
+ * to know what token to return the next time the lexer is called. Caller
+ * will need to set PL_nextval[], and possibly PL_expect to ensure the lexer
+ * handles the token correctly.
*/
STATIC void
* it calls S_force_word to stick the next word into the PL_next lookahead.
*
* Arguments:
- * char *start : start of the buffer
+ * char *start : buffer position (must be within PL_linestr)
* int token : PL_next will be this type of bare word (e.g., METHOD,WORD)
* int check_keyword : if true, Perl checks to make sure the word isn't
* a keyword (do this if the word is a label, e.g. goto FOO)
* int allow_pack : if true, : characters will also be allowed (require,
* use, etc. do this)
- * int allow_initial_tick : used by the "sub" tokenizer only.
+ * int allow_initial_tick : used by the "sub" lexer only.
*/
STATIC char *
/*
* S_force_ident
- * Called when the tokenizer wants $foo *foo &foo etc, but the program
+ * Called when the lexer wants $foo *foo &foo etc, but the program
* text only contains the "foo" portion. The first argument is a pointer
* to the "foo", and the second argument is the type symbol to prefix.
* Forces the next token to be a "WORD".
- * Creates the symbol if it didn't already exist (through the gv_fetchpv
- * call).
+ * Creates the symbol if it didn't already exist (via gv_fetchpv()).
*/
STATIC void
PL_linestr = PL_lex_stuff;
PL_lex_stuff = Nullsv;
- PL_bufend = PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart = SvPVX(PL_linestr);
+ PL_bufend = PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart
+ = SvPVX(PL_linestr);
PL_bufend += SvCUR(PL_linestr);
SAVEFREESV(PL_linestr);
PL_bufend = SvPVX(PL_linestr);
PL_bufend += SvCUR(PL_linestr);
PL_expect = XOPERATOR;
+ PL_sublex_info.sub_inwhat = 0;
return ')';
}
}
? (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))
+ ? (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 =
+ const char *leaveit = /* set of acceptably-backslashed characters */
PL_lex_inpat
? "\\.^$@AGZdDwWsSbBpPXC+*?|()-nrtfeaxcz0123456789[{]} \t\n\r\f\v#"
: "";
I32 max; /* last character in range */
i = d - SvPVX(sv); /* remember current offset */
- SvGROW(sv, SvLEN(sv) + 256); /* expand the sv -- there'll never be more'n 256 chars in a range for it to grow by */
- d = SvPVX(sv) + i; /* restore d after the grow potentially has changed the ptr */
+ SvGROW(sv, SvLEN(sv) + 256); /* never more than 256 chars in a range */
+ d = SvPVX(sv) + i; /* refresh d after realloc */
d -= 2; /* eat the first char and the - */
min = (U8)*d; /* first char in range */
/* \132 indicates an octal constant */
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
- *d++ = scan_oct(s, 3, &len);
+ *d++ = (char)scan_oct(s, 3, &len);
s += len;
continue;
}
/* note: utf always shorter than hex */
d = (char*)uv_to_utf8((U8*)d,
- scan_hex(s + 1, e - s - 1, &len));
+ (UV)scan_hex(s + 1, e - s - 1, &len));
s = e + 1;
}
else {
}
continue;
+ /* \N{latin small letter a} is a named character */
+ case 'N':
+ ++s;
+ if (*s == '{') {
+ char* e = strchr(s, '}');
+ HV *hv;
+ SV **svp;
+ SV *res, *cv;
+ STRLEN len;
+ char *str;
+ char *why = Nullch;
+
+ if (!e) {
+ yyerror("Missing right brace on \\N{}");
+ e = s - 1;
+ goto cont_scan;
+ }
+ res = newSVpvn(s + 1, e - s - 1);
+ res = new_constant( Nullch, 0, "charnames",
+ res, Nullsv, "\\N{...}" );
+ str = SvPV(res,len);
+ if (len > e - s + 4) {
+ char *odest = SvPVX(sv);
+
+ SvGROW(sv, (SvCUR(sv) + len - (e - s + 4)));
+ d = SvPVX(sv) + (d - odest);
+ }
+ Copy(str, d, len, char);
+ d += len;
+ SvREFCNT_dec(res);
+ cont_scan:
+ s = e + 1;
+ }
+ else
+ yyerror("Missing braces on \\N{}");
+ continue;
+
/* \c is a control character */
case 'c':
s++;
/* S_intuit_more
* Returns TRUE if there's more to the expression (e.g., a subscript),
* FALSE otherwise.
- * This is the one truly awful dwimmer necessary to conflate C and sed.
*
* It deals with "$foo[3]" and /$foo[3]/ and /$foo[0123456789$]+/
*
* anything else returns TRUE
*/
+/* This is the one truly awful dwimmer necessary to conflate C and sed. */
+
STATIC int
S_intuit_more(pTHX_ register char *s)
{
SV *
Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
{
- if (!funcp){ /* temporary handy debugging hack to be deleted */
- PL_filter_debug = atoi((char*)datasv);
- return NULL;
- }
+ if (!funcp)
+ return Nullsv;
+
if (!PL_rsfp_filters)
PL_rsfp_filters = newAV();
if (!datasv)
if (!SvUPGRADE(datasv, SVt_PVIO))
Perl_die(aTHX_ "Can't upgrade filter_add data to SVt_PVIO");
IoDIRP(datasv) = (DIR*)funcp; /* stash funcp into spare field */
-#ifdef DEBUGGING
- if (PL_filter_debug) {
- STRLEN n_a;
- Perl_warn(aTHX_ "filter_add func %p (%s)", funcp, SvPV(datasv, n_a));
- }
-#endif /* DEBUGGING */
+ DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_add func %p (%s)\n",
+ funcp, SvPV_nolen(datasv)));
av_unshift(PL_rsfp_filters, 1);
av_store(PL_rsfp_filters, 0, datasv) ;
return(datasv);
void
Perl_filter_del(pTHX_ filter_t funcp)
{
-#ifdef DEBUGGING
- if (PL_filter_debug)
- Perl_warn(aTHX_ "filter_del func %p", funcp);
-#endif /* DEBUGGING */
+ DEBUG_P(PerlIO_printf(Perl_debug_log, "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 (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. */
-#ifdef DEBUGGING
- if (PL_filter_debug)
- Perl_warn(aTHX_ "filter_read %d: from rsfp\n", idx);
-#endif /* DEBUGGING */
+ DEBUG_P(PerlIO_printf(Perl_debug_log,
+ "filter_read %d: from rsfp\n", idx));
if (maxlen) {
/* Want a block */
int len ;
}
/* Skip this filter slot if filter has been deleted */
if ( (datasv = FILTER_DATA(idx)) == &PL_sv_undef){
-#ifdef DEBUGGING
- if (PL_filter_debug)
- Perl_warn(aTHX_ "filter_read %d: skipped (filter deleted)\n", idx);
-#endif /* DEBUGGING */
+ DEBUG_P(PerlIO_printf(Perl_debug_log,
+ "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);
-#ifdef DEBUGGING
- if (PL_filter_debug) {
- STRLEN n_a;
- Perl_warn(aTHX_ "filter_read %d: via function %p (%s)\n",
- idx, funcp, SvPV(datasv,n_a));
- }
-#endif /* DEBUGGING */
+ DEBUG_P(PerlIO_printf(Perl_debug_log,
+ "filter_read %d: via function %p (%s)\n",
+ idx, funcp, SvPV_nolen(datasv)));
/* Call function. The function is expected to */
/* call "FILTER_READ(idx+1, buf_sv)" first. */
/* Return: <0:error, =0:eof, >0:not eof */
#ifdef DEBUGGING
static char* exp_name[] =
- { "OPERATOR", "TERM", "REF", "STATE", "BLOCK", "TERMBLOCK" };
+ { "OPERATOR", "TERM", "REF", "STATE", "BLOCK", "ATTRBLOCK",
+ "ATTRTERM", "TERMBLOCK"
+ };
#endif
/*
if it's a legal name, the OP is a PADANY.
*/
if (PL_in_my) {
- if (strchr(PL_tokenbuf,':'))
- yyerror(Perl_form(aTHX_ PL_no_myglob,PL_tokenbuf));
+ if (PL_in_my == KEY_our) { /* "our" is merely analogous to "my" */
+ tmp = pad_allocmy(PL_tokenbuf);
+ }
+ else {
+ if (strchr(PL_tokenbuf,':'))
+ yyerror(Perl_form(aTHX_ PL_no_myglob,PL_tokenbuf));
- yylval.opval = newOP(OP_PADANY, 0);
- yylval.opval->op_targ = pad_allocmy(PL_tokenbuf);
- return PRIVATEREF;
+ yylval.opval = newOP(OP_PADANY, 0);
+ yylval.opval->op_targ = pad_allocmy(PL_tokenbuf);
+ return PRIVATEREF;
+ }
}
/*
}
#endif /* USE_THREADS */
if ((tmp = pad_findmy(PL_tokenbuf)) != NOT_IN_PAD) {
+ /* might be an "our" variable" */
+ if (SvFLAGS(AvARRAY(PL_comppad_name)[tmp]) & SVpad_OUR) {
+ /* build ops for a bareword */
+ yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf+1, 0));
+ yylval.opval->op_private = OPpCONST_ENTERED;
+ gv_fetchpv(PL_tokenbuf+1,
+ (PL_in_eval
+ ? (GV_ADDMULTI | GV_ADDINEVAL | GV_ADDOUR)
+ : GV_ADDOUR
+ ),
+ ((PL_tokenbuf[0] == '$') ? SVt_PV
+ : (PL_tokenbuf[0] == '@') ? SVt_PVAV
+ : SVt_PVHV));
+ return WORD;
+ }
+
/* if it's a sort block and they're naming $a or $b */
if (PL_last_lop_op == OP_SORT &&
PL_tokenbuf[0] == '$' &&
break;
#endif
- /* when we're already built the next token, just pull it out the queue */
+ /* when we've already built the next token, just pull it out of the queue */
case LEX_KNOWNEXT:
PL_nexttoke--;
yylval = PL_nextval[PL_nexttoke];
PL_oldoldbufptr = PL_oldbufptr;
PL_oldbufptr = s;
DEBUG_p( {
- PerlIO_printf(PerlIO_stderr(), "### Tokener expecting %s at %s\n", exp_name[PL_expect], s);
+ PerlIO_printf(Perl_debug_log, "### Tokener expecting %s at %s\n",
+ exp_name[PL_expect], s);
} )
retry:
sv_upgrade(sv, SVt_PVMG);
sv_setsv(sv,PL_linestr);
- av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
+ av_store(CopFILEAV(PL_curcop),(I32)PL_curcop->cop_line,sv);
}
goto retry;
}
sv_upgrade(sv, SVt_PVMG);
sv_setsv(sv,PL_linestr);
- av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
+ av_store(CopFILEAV(PL_curcop),(I32)PL_curcop->cop_line,sv);
}
PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
if (PL_curcop->cop_line == 1) {
*/
SV *x = GvSV(gv_fetchpv("\030", TRUE, SVt_PV));
assert(SvPOK(x) || SvGMAGICAL(x));
- if (sv_eq(x, GvSV(PL_curcop->cop_filegv))) {
+ if (sv_eq(x, CopFILESV(PL_curcop))) {
sv_setpvn(x, ipath, ipathend - ipath);
SvSETMAGIC(x);
}
* Look for options.
*/
d = instr(s,"perl -");
- if (!d)
+ if (!d) {
d = instr(s,"perl");
+#if defined(DOSISH)
+ /* avoid getting into infinite loops when shebang
+ * line contains "Perl" rather than "perl" */
+ if (!d) {
+ for (d = ipathend-4; d >= ipath; --d) {
+ if ((*d == 'p' || *d == 'P')
+ && !ibcmp(d, "perl", 4))
+ {
+ break;
+ }
+ }
+ if (d < ipath)
+ d = Nullch;
+ }
+#endif
+ }
#ifdef ALTERNATE_SHEBANG
/*
* If the ALTERNATE_SHEBANG on this system starts with a
*s = '#'; /* Don't try to parse shebang line */
}
#endif /* ALTERNATE_SHEBANG */
+#ifndef MACOS_TRADITIONAL
if (!d &&
*s == '#' &&
ipathend > ipath &&
PerlProc_execv(ipath, newargv);
Perl_croak(aTHX_ "Can't exec %s", ipath);
}
+#endif
if (d) {
U32 oldpdb = PL_perldb;
bool oldn = PL_minus_n;
bool oldp = PL_minus_p;
while (*d && !isSPACE(*d)) d++;
- while (*d == ' ' || *d == '\t') d++;
+ while (SPACE_OR_TAB(*d)) d++;
if (*d++ == '-') {
do {
"(Maybe you didn't strip carriage returns after a network transfer?)\n");
#endif
case ' ': case '\t': case '\f': case 013:
+#ifdef MACOS_TRADITIONAL
+ case '\312': /* Them nonbreaking spaces again */
+#endif
s++;
goto retry;
case '#':
PL_bufptr = s;
tmp = *s++;
- while (s < PL_bufend && (*s == ' ' || *s == '\t'))
+ while (s < PL_bufend && SPACE_OR_TAB(*s))
s++;
if (strnEQ(s,"=>",2)) {
goto just_a_word;
}
s++;
+ switch (PL_expect) {
+ OP *attrs;
+ case XOPERATOR:
+ if (!PL_in_my || PL_lex_state != LEX_NORMAL)
+ break;
+ PL_bufptr = s; /* update in case we back off */
+ goto grabattrs;
+ case XATTRBLOCK:
+ PL_expect = XBLOCK;
+ goto grabattrs;
+ case XATTRTERM:
+ PL_expect = XTERMBLOCK;
+ grabattrs:
+ s = skipspace(s);
+ attrs = Nullop;
+ while (isIDFIRST_lazy(s)) {
+ d = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, FALSE, &len);
+ if (*d == '(') {
+ d = scan_str(d,TRUE,TRUE);
+ if (!d) {
+ if (PL_lex_stuff) {
+ SvREFCNT_dec(PL_lex_stuff);
+ PL_lex_stuff = Nullsv;
+ }
+ /* MUST advance bufptr here to avoid bogus
+ "at end of line" context messages from yyerror().
+ */
+ PL_bufptr = s + len;
+ yyerror("Unterminated attribute parameter in attribute list");
+ if (attrs)
+ op_free(attrs);
+ return 0; /* EOF indicator */
+ }
+ }
+ if (PL_lex_stuff) {
+ SV *sv = newSVpvn(s, len);
+ sv_catsv(sv, PL_lex_stuff);
+ attrs = append_elem(OP_LIST, attrs,
+ newSVOP(OP_CONST, 0, sv));
+ SvREFCNT_dec(PL_lex_stuff);
+ PL_lex_stuff = Nullsv;
+ }
+ else {
+ attrs = append_elem(OP_LIST, attrs,
+ newSVOP(OP_CONST, 0,
+ newSVpvn(s, len)));
+ }
+ s = skipspace(d);
+ while (*s == ',')
+ s = skipspace(s+1);
+ }
+ tmp = (PL_expect == XOPERATOR ? '=' : '{'); /*'}' for vi */
+ if (*s != ';' && *s != tmp) {
+ char q = ((*s == '\'') ? '"' : '\'');
+ /* If here for an expression, and parsed no attrs, back off. */
+ if (tmp == '=' && !attrs) {
+ s = PL_bufptr;
+ break;
+ }
+ /* MUST advance bufptr here to avoid bogus "at end of line"
+ context messages from yyerror().
+ */
+ PL_bufptr = s;
+ if (!*s)
+ yyerror("Unterminated attribute list");
+ else
+ yyerror(Perl_form(aTHX_ "Invalid separator character %c%c%c in attribute list",
+ q, *s, q));
+ if (attrs)
+ op_free(attrs);
+ OPERATOR(':');
+ }
+ if (attrs) {
+ PL_nextval[PL_nexttoke].opval = attrs;
+ force_next(THING);
+ }
+ TOKEN(COLONATTR);
+ }
OPERATOR(':');
case '(':
s++;
PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
OPERATOR(HASHBRACK);
case XOPERATOR:
- while (s < PL_bufend && (*s == ' ' || *s == '\t'))
+ while (s < PL_bufend && SPACE_OR_TAB(*s))
s++;
d = s;
PL_tokenbuf[0] = '\0';
if (d < PL_bufend && *d == '-') {
PL_tokenbuf[0] = '-';
d++;
- while (d < PL_bufend && (*d == ' ' || *d == '\t'))
+ while (d < PL_bufend && SPACE_OR_TAB(*d))
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'))
+ while (d < PL_bufend && SPACE_OR_TAB(*d))
d++;
if (*d == '}') {
char minus = (PL_tokenbuf[0] == '-');
}
}
/* FALL THROUGH */
+ case XATTRBLOCK:
case XBLOCK:
PL_lex_brackstack[PL_lex_brackets++] = XSTATE;
PL_expect = XSTATE;
break;
+ case XATTRTERM:
case XTERMBLOCK:
PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
PL_expect = XSTATE;
if (PL_lex_brackets < PL_lex_formbrack) {
char *t;
#ifdef PERL_STRICT_CR
- for (t = s; *t == ' ' || *t == '\t'; t++) ;
+ for (t = s; SPACE_OR_TAB(*t); t++) ;
#else
- for (t = s; *t == ' ' || *t == '\t' || *t == '\r'; t++) ;
+ for (t = s; SPACE_OR_TAB(*t) || *t == '\r'; t++) ;
#endif
if (*t == '\n' || *t == '#') {
s--;
TERM(THING);
case '\'':
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (PL_expect == XOPERATOR) {
if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack) {
PL_expect = XTERM;
TERM(sublex_start());
case '"':
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (PL_expect == XOPERATOR) {
if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack) {
PL_expect = XTERM;
TERM(sublex_start());
case '`':
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (PL_expect == XOPERATOR)
no_op("Backticks",s);
if (!s)
if (PL_oldoldbufptr &&
PL_oldoldbufptr < PL_bufptr &&
- (PL_oldoldbufptr == PL_last_lop || PL_oldoldbufptr == PL_last_uni) &&
+ (PL_oldoldbufptr == PL_last_lop
+ || PL_oldoldbufptr == PL_last_uni) &&
/* NO SKIPSPACE BEFORE HERE! */
(PL_expect == XREF ||
((PL_opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF))
if (*s == '(') {
CLINE;
if (gv && GvCVu(gv)) {
- for (d = s + 1; *d == ' ' || *d == '\t'; d++) ;
+ for (d = s + 1; SPACE_OR_TAB(*d); d++) ;
if (*d == ')' && (sv = cv_const_sv(GvCV(gv)))) {
s = d + 1;
goto its_constant;
case KEY___FILE__:
yylval.opval = (OP*)newSVOP(OP_CONST, 0,
- newSVsv(GvSV(PL_curcop->cop_filegv)));
+ newSVsv(CopFILESV(PL_curcop)));
TERM(THING);
case KEY___LINE__:
- yylval.opval = (OP*)newSVOP(OP_CONST, 0,
- Perl_newSVpvf(aTHX_ "%ld", (long)PL_curcop->cop_line));
+ yylval.opval = (OP*)newSVOP(OP_CONST, 0,
+ Perl_newSVpvf(aTHX_ "%"IVdf, (IV)PL_curcop->cop_line));
TERM(THING);
case KEY___PACKAGE__:
case KEY_DESTROY:
case KEY_BEGIN:
case KEY_END:
+ case KEY_STOP:
case KEY_INIT:
if (PL_expect == XSTATE) {
s = PL_bufptr;
case KEY_crypt:
#ifdef FCRYPT
- if (!PL_cryptseen++)
+ if (!PL_cryptseen) {
+ PL_cryptseen = TRUE;
init_des();
+ }
#endif
LOP(OP_CRYPT,XTERM);
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");
+ Perl_warner(aTHX_ WARN_OCTAL,
+ "chmod: mode argument is missing initial 0");
}
LOP(OP_CHMOD,XTERM);
if ((PL_bufend - p) >= 3 &&
strnEQ(p, "my", 2) && isSPACE(*(p + 2)))
p += 2;
+ else if ((PL_bufend - p) >= 4 &&
+ strnEQ(p, "our", 3) && isSPACE(*(p + 3)))
+ p += 3;
p = skipspace(p);
- if (isIDFIRST_lazy(p))
+ if (isIDFIRST_lazy(p)) {
+ p = scan_ident(p, PL_bufend,
+ PL_tokenbuf, sizeof PL_tokenbuf, TRUE);
+ p = skipspace(p);
+ }
+ if (*p != '$')
Perl_croak(aTHX_ "Missing $ on loop variable");
}
OPERATOR(FOR);
UNI(OP_LCFIRST);
case KEY_local:
+ yylval.ival = 0;
OPERATOR(LOCAL);
case KEY_length:
case KEY_msgsnd:
LOP(OP_MSGSND,XTERM);
+ case KEY_our:
case KEY_my:
- PL_in_my = TRUE;
+ PL_in_my = tmp;
s = skipspace(s);
if (isIDFIRST_lazy(s)) {
s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, TRUE, &len);
+ if (len == 3 && strnEQ(PL_tokenbuf, "sub", 3))
+ goto really_sub;
PL_in_my_stash = gv_stashpv(PL_tokenbuf, FALSE);
if (!PL_in_my_stash) {
char tmpbuf[1024];
yyerror(tmpbuf);
}
}
+ yylval.ival = 1;
OPERATOR(MY);
case KEY_next:
OPERATOR(USE);
case KEY_not:
- OPERATOR(NOTOP);
+ if (*s == '(' || (s = skipspace(s), *s == '('))
+ FUN1(OP_NOT);
+ else
+ OPERATOR(NOTOP);
case KEY_open:
s = skipspace(s);
LOP(OP_PIPE_OP,XTERM);
case KEY_q:
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (!s)
missingterm((char*)0);
yylval.ival = OP_CONST;
UNI(OP_QUOTEMETA);
case KEY_qw:
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (!s)
missingterm((char*)0);
force_next(')');
TOKEN('(');
case KEY_qq:
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (!s)
missingterm((char*)0);
yylval.ival = OP_STRINGIFY;
TERM(sublex_start());
case KEY_qx:
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (!s)
missingterm((char*)0);
yylval.ival = OP_BACKTICK;
UNI(OP_STAT);
case KEY_study:
- PL_sawstudy++;
UNI(OP_STUDY);
case KEY_substr:
case KEY_format:
case KEY_sub:
really_sub:
- s = skipspace(s);
-
- if (isIDFIRST_lazy(s) || *s == '\'' || *s == ':') {
+ {
char tmpbuf[sizeof PL_tokenbuf];
- PL_expect = XBLOCK;
- d = scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len);
- if (strchr(tmpbuf, ':'))
- sv_setpv(PL_subname, tmpbuf);
+ SSize_t tboffset;
+ expectation attrful;
+ bool have_name, have_proto;
+ int key = tmp;
+
+ s = skipspace(s);
+
+ if (isIDFIRST_lazy(s) || *s == '\'' ||
+ (*s == ':' && s[1] == ':'))
+ {
+ PL_expect = XBLOCK;
+ attrful = XATTRBLOCK;
+ /* remember buffer pos'n for later force_word */
+ tboffset = s - PL_oldbufptr;
+ d = scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len);
+ if (strchr(tmpbuf, ':'))
+ sv_setpv(PL_subname, tmpbuf);
+ else {
+ sv_setsv(PL_subname,PL_curstname);
+ sv_catpvn(PL_subname,"::",2);
+ sv_catpvn(PL_subname,tmpbuf,len);
+ }
+ s = skipspace(d);
+ have_name = TRUE;
+ }
else {
- sv_setsv(PL_subname,PL_curstname);
- sv_catpvn(PL_subname,"::",2);
- sv_catpvn(PL_subname,tmpbuf,len);
+ if (key == KEY_my)
+ Perl_croak(aTHX_ "Missing name in \"my sub\"");
+ PL_expect = XTERMBLOCK;
+ attrful = XATTRTERM;
+ sv_setpv(PL_subname,"?");
+ have_name = FALSE;
}
- s = force_word(s,WORD,FALSE,TRUE,TRUE);
- s = skipspace(s);
- }
- else {
- PL_expect = XTERMBLOCK;
- sv_setpv(PL_subname,"?");
- }
- if (tmp == KEY_format) {
- s = skipspace(s);
- if (*s == '=')
- PL_lex_formbrack = PL_lex_brackets + 1;
- OPERATOR(FORMAT);
- }
+ if (key == KEY_format) {
+ if (*s == '=')
+ PL_lex_formbrack = PL_lex_brackets + 1;
+ if (have_name)
+ (void) force_word(PL_oldbufptr + tboffset, WORD,
+ FALSE, TRUE, TRUE);
+ OPERATOR(FORMAT);
+ }
- /* Look for a prototype */
- if (*s == '(') {
- char *p;
+ /* Look for a prototype */
+ if (*s == '(') {
+ char *p;
+
+ s = scan_str(s,FALSE,FALSE);
+ if (!s) {
+ if (PL_lex_stuff)
+ SvREFCNT_dec(PL_lex_stuff);
+ PL_lex_stuff = Nullsv;
+ Perl_croak(aTHX_ "Prototype not terminated");
+ }
+ /* strip spaces */
+ d = SvPVX(PL_lex_stuff);
+ tmp = 0;
+ for (p = d; *p; ++p) {
+ if (!isSPACE(*p))
+ d[tmp++] = *p;
+ }
+ d[tmp] = '\0';
+ SvCUR(PL_lex_stuff) = tmp;
+ have_proto = TRUE;
- s = scan_str(s);
- if (!s) {
- if (PL_lex_stuff)
- SvREFCNT_dec(PL_lex_stuff);
- PL_lex_stuff = Nullsv;
- Perl_croak(aTHX_ "Prototype not terminated");
+ s = skipspace(s);
}
- /* strip spaces */
- d = SvPVX(PL_lex_stuff);
- tmp = 0;
- for (p = d; *p; ++p) {
- if (!isSPACE(*p))
- d[tmp++] = *p;
+ else
+ have_proto = FALSE;
+
+ if (*s == ':' && s[1] != ':')
+ PL_expect = attrful;
+
+ if (have_proto) {
+ PL_nextval[PL_nexttoke].opval =
+ (OP*)newSVOP(OP_CONST, 0, PL_lex_stuff);
+ PL_lex_stuff = Nullsv;
+ force_next(THING);
}
- d[tmp] = '\0';
- SvCUR(PL_lex_stuff) = tmp;
-
- PL_nexttoke++;
- PL_nextval[1] = PL_nextval[0];
- PL_nexttype[1] = PL_nexttype[0];
- PL_nextval[0].opval = (OP*)newSVOP(OP_CONST, 0, PL_lex_stuff);
- PL_nexttype[0] = THING;
- if (PL_nexttoke == 1) {
- PL_lex_defer = PL_lex_state;
- PL_lex_expect = PL_expect;
- PL_lex_state = LEX_KNOWNEXT;
+ if (!have_name) {
+ sv_setpv(PL_subname,"__ANON__");
+ TOKEN(ANONSUB);
}
- PL_lex_stuff = Nullsv;
- }
-
- if (*SvPV(PL_subname,n_a) == '?') {
- sv_setpv(PL_subname,"__ANON__");
- TOKEN(ANONSUB);
+ (void) force_word(PL_oldbufptr + tboffset, WORD,
+ FALSE, TRUE, TRUE);
+ if (key == KEY_my)
+ TOKEN(MYSUB);
+ TOKEN(SUB);
}
- PREBLOCK(SUB);
case KEY_system:
set_csh();
case KEY_umask:
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");
+ if (*d != '0' && isDIGIT(*d))
+ Perl_warner(aTHX_ WARN_OCTAL,
+ "umask: argument is missing initial 0");
}
UNI(OP_UMASK);
UNI(OP_VALUES);
case KEY_vec:
- PL_sawvec = TRUE;
LOP(OP_VEC,XTERM);
case KEY_while:
case 3:
if (strEQ(d,"ord")) return -KEY_ord;
if (strEQ(d,"oct")) return -KEY_oct;
- if (strEQ(d,"our")) { deprecate("reserved word \"our\"");
- return 0;}
+ if (strEQ(d,"our")) return KEY_our;
break;
case 4:
if (strEQ(d,"open")) return -KEY_open;
break;
}
break;
+ case 'S':
+ if (strEQ(d,"STOP")) return KEY_STOP;
+ break;
case 's':
switch (d[1]) {
case 0: return KEY_s;
if (*w)
for (; *w && isSPACE(*w); w++) ;
if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */
- Perl_warner(aTHX_ WARN_SYNTAX, "%s (...) interpreted as function",name);
+ Perl_warner(aTHX_ WARN_SYNTAX,
+ "%s (...) interpreted as function",name);
}
}
while (s < PL_bufend && isSPACE(*s))
}
}
+/* Either returns sv, or mortalizes sv and returns a new SV*.
+ Best used as sv=new_constant(..., sv, ...).
+ If s, pv are NULL, calls subroutine with one argument,
+ and type is used with error messages only. */
+
STATIC SV *
-S_new_constant(pTHX_ char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
+S_new_constant(pTHX_ char *s, STRLEN len, const char *key, SV *sv, SV *pv,
+ const char *type)
{
dSP;
HV *table = GvHV(PL_hintgv); /* ^H */
- BINOP myop;
SV *res;
- bool oldcatch = CATCH_GET;
SV **cvp;
SV *cv, *typesv;
-
+ const char *why, *why1, *why2;
+
+ if (!(PL_hints & HINT_LOCALIZE_HH)) {
+ SV *msg;
+
+ why = "%^H is not localized";
+ report_short:
+ why1 = why2 = "";
+ report:
+ msg = Perl_newSVpvf(aTHX_ "constant(%s): %s%s%s",
+ (type ? type: "undef"), why1, why2, why);
+ yyerror(SvPVX(msg));
+ SvREFCNT_dec(msg);
+ return sv;
+ }
if (!table) {
- yyerror("%^H is not defined");
- return sv;
+ why = "%^H is not defined";
+ goto report_short;
}
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;
+ why = "} is not defined";
+ why1 = "$^H{";
+ why2 = key;
+ goto report;
}
sv_2mortal(sv); /* Parent created it permanently */
cv = *cvp;
- if (!pv)
- pv = sv_2mortal(newSVpvn(s, len));
- if (type)
- typesv = sv_2mortal(newSVpv(type, 0));
+ if (!pv && s)
+ pv = sv_2mortal(newSVpvn(s, len));
+ if (type && pv)
+ typesv = sv_2mortal(newSVpv(type, 0));
else
- typesv = &PL_sv_undef;
- CATCH_SET(TRUE);
- Zero(&myop, 1, BINOP);
- myop.op_last = (OP *) &myop;
- myop.op_next = Nullop;
- myop.op_flags = OPf_WANT_SCALAR | OPf_STACKED;
-
+ typesv = &PL_sv_undef;
+
PUSHSTACKi(PERLSI_OVERLOAD);
- ENTER;
- SAVEOP();
- PL_op = (OP *) &myop;
- if (PERLDB_SUB && PL_curstash != PL_debstash)
- PL_op->op_private |= OPpENTERSUB_DB;
- PUTBACK;
- Perl_pp_pushmark(aTHX);
-
+ ENTER ;
+ SAVETMPS;
+
+ PUSHMARK(SP) ;
EXTEND(sp, 4);
- PUSHs(pv);
+ if (pv)
+ PUSHs(pv);
PUSHs(sv);
- PUSHs(typesv);
+ if (pv)
+ PUSHs(typesv);
PUSHs(cv);
PUTBACK;
-
- if (PL_op = Perl_pp_entersub(aTHX))
- CALLRUNOPS(aTHX);
- LEAVE;
- SPAGAIN;
-
- res = POPs;
- PUTBACK;
- CATCH_SET(oldcatch);
+ call_sv(cv, G_SCALAR | ( PL_in_eval ? 0 : G_EVAL));
+
+ SPAGAIN ;
+
+ /* Check the eval first */
+ if (!PL_in_eval && SvTRUE(ERRSV))
+ {
+ STRLEN n_a;
+ sv_catpv(ERRSV, "Propagated");
+ yyerror(SvPV(ERRSV, n_a)); /* Duplicates the message inside eval */
+ (void)POPs;
+ res = SvREFCNT_inc(sv);
+ }
+ else {
+ res = POPs;
+ (void)SvREFCNT_inc(res);
+ }
+
+ PUTBACK ;
+ FREETMPS ;
+ LEAVE ;
POPSTACK;
-
+
if (!SvOK(res)) {
- char buf[128];
- sprintf(buf,"Call to &{$^H{%s}} did not return a defined value", key);
- yyerror(buf);
- }
- return SvREFCNT_inc(res);
+ why = "}} did not return a defined value";
+ why1 = "Call to &{$^H{";
+ why2 = key;
+ sv = res;
+ goto report;
+ }
+
+ return res;
}
-
+
STATIC char *
S_scan_word(pTHX_ register char *s, char *dest, STRLEN destlen, int allow_package, STRLEN *slp)
{
if (isSPACE(s[-1])) {
while (s < send) {
char ch = *s++;
- if (ch != ' ' && ch != '\t') {
+ if (!SPACE_OR_TAB(ch)) {
*d = ch;
break;
}
Perl_croak(aTHX_ ident_too_long);
}
*d = '\0';
- while (s < send && (*s == ' ' || *s == '\t')) s++;
+ while (s < send && SPACE_OR_TAB(*s)) s++;
if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) {
dTHR; /* only for ckWARN */
if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) {
- char *brack = *s == '[' ? "[...]" : "{...}";
+ const char *brack = *s == '[' ? "[...]" : "{...}";
Perl_warner(aTHX_ WARN_AMBIGUOUS,
"Ambiguous use of %c{%s%s} resolved to %c%s%s",
funny, dest, brack, funny, dest, brack);
PMOP *pm;
char *s;
- s = scan_str(start);
+ s = scan_str(start,FALSE,FALSE);
if (!s) {
if (PL_lex_stuff)
SvREFCNT_dec(PL_lex_stuff);
yylval.ival = OP_NULL;
- s = scan_str(start);
+ s = scan_str(start,FALSE,FALSE);
if (!s) {
if (PL_lex_stuff)
s--;
first_start = PL_multi_start;
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (!s) {
if (PL_lex_stuff)
SvREFCNT_dec(PL_lex_stuff);
yylval.ival = OP_NULL;
- s = scan_str(start);
+ s = scan_str(start,FALSE,FALSE);
if (!s) {
if (PL_lex_stuff)
SvREFCNT_dec(PL_lex_stuff);
if (s[-1] == PL_multi_open)
s--;
- s = scan_str(s);
+ s = scan_str(s,FALSE,FALSE);
if (!s) {
if (PL_lex_stuff)
SvREFCNT_dec(PL_lex_stuff);
e = PL_tokenbuf + sizeof PL_tokenbuf - 1;
if (!outer)
*d++ = '\n';
- for (peek = s; *peek == ' ' || *peek == '\t'; peek++) ;
+ for (peek = s; SPACE_OR_TAB(*peek); peek++) ;
if (*peek && strchr("`'\"",*peek)) {
s = peek;
term = *s++;
sv_upgrade(sv, SVt_PVMG);
sv_setsv(sv,PL_linestr);
- av_store(GvAV(PL_curcop->cop_filegv),
- (I32)PL_curcop->cop_line,sv);
+ av_store(CopFILEAV(PL_curcop), (I32)PL_curcop->cop_line,sv);
}
if (*s == term && memEQ(s,PL_tokenbuf,len)) {
s = PL_bufend - 1;
if (d - PL_tokenbuf != len) {
yylval.ival = OP_GLOB;
set_csh();
- s = scan_str(start);
+ s = scan_str(start,FALSE,FALSE);
if (!s)
Perl_croak(aTHX_ "Glob not terminated");
return s;
/* scan_str
takes: start position in buffer
+ keep_quoted preserve \ on the embedded delimiter(s)
+ keep_delims preserve the delimiters around the string
returns: position to continue reading from buffer
side-effects: multi_start, multi_close, lex_repl or lex_stuff, and
updates the read buffer.
tr/// string transliterate tr/this/that/
y/// string transliterate y/this/that/
($*@) sub prototypes sub foo ($)
+ (stuff) sub attr parameters sub foo : attr(stuff)
<> readline or globs <FOO>, <>, <$fh>, or <*.c>
In most of these cases (all but <>, patterns and transliterate)
*/
STATIC char *
-S_scan_str(pTHX_ char *start)
+S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
{
dTHR;
SV *sv; /* scalar value: string */
(void)SvPOK_only(sv); /* validate pointer */
/* move past delimiter and try to read a complete string */
+ if (keep_delims)
+ sv_catpvn(sv, s, 1);
s++;
for (;;) {
/* extend sv if need be */
SvGROW(sv, SvCUR(sv) + (PL_bufend - s) + 1);
/* set 'to' to the next character in the sv's string */
to = SvPVX(sv)+SvCUR(sv);
-
+
/* if open delimiter is the close delimiter read unbridle */
if (PL_multi_open == PL_multi_close) {
for (; s < PL_bufend; s++,to++) {
PL_curcop->cop_line++;
/* handle quoted delimiters */
if (*s == '\\' && s+1 < PL_bufend && term != '\\') {
- if (s[1] == term)
+ if (!keep_quoted && s[1] == term)
s++;
/* any other quotes are simply copied straight through */
else
PL_curcop->cop_line++;
/* backslashes can escape the open or closing characters */
if (*s == '\\' && s+1 < PL_bufend) {
- if ((s[1] == PL_multi_open) || (s[1] == PL_multi_close))
+ if (!keep_quoted &&
+ ((s[1] == PL_multi_open) || (s[1] == PL_multi_close)))
s++;
else
*to++ = *s++;
sv_upgrade(sv, SVt_PVMG);
sv_setsv(sv,PL_linestr);
- av_store(GvAV(PL_curcop->cop_filegv),
- (I32)PL_curcop->cop_line, sv);
+ av_store(CopFILEAV(PL_curcop), (I32)PL_curcop->cop_line, sv);
}
/* having changed the buffer, we must update PL_bufend */
/* at this point, we have successfully read the delimited string */
+ if (keep_delims)
+ sv_catpvn(sv, s, 1);
PL_multi_end = PL_curcop->cop_line;
s++;
register char *s = start; /* current position in buffer */
register char *d; /* destination in temp buffer */
register char *e; /* end of temp buffer */
- I32 tryiv; /* used to see if it can be an int */
+ 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 */
- I32 floatit; /* boolean: int or float? */
+ bool floatit; /* boolean: int or float? */
char *lastub = 0; /* position of last underbar */
static char number_too_long[] = "Number too long";
static char *maxima[5] = { "",
"0b11111111111111111111111111111111",
"",
- "0b37777777777",
+ "037777777777",
"0xffffffff" };
char *base, *Base, *max;
s += 2;
}
/* check for a decimal in disguise */
- else if (s[1] == '.')
+ else if (s[1] == '.' || s[1] == 'e' || s[1] == 'E')
goto decimal;
/* so it must be octal */
else
/* read the rest of the number */
for (;;) {
/* x is used in the overflow test,
- b is the digit we're adding on */
+ b is the digit we're adding on. */
UV x, b;
switch (*s) {
case '8': case '9':
if (shift == 3)
yyerror(Perl_form(aTHX_ "Illegal octal digit '%c'", *s));
- else
- if (shift == 1)
- yyerror(Perl_form(aTHX_ "Illegal binary digit '%c'", *s));
/* FALL THROUGH */
/* octal digits */
dTHR;
overflowed = TRUE;
n = (NV) u;
- if (ckWARN_d(WARN_UNSAFE))
- Perl_warner(aTHX_ ((shift == 3) ?
- WARN_OCTAL : WARN_UNSAFE),
+ if (ckWARN_d(WARN_OVERFLOW))
+ Perl_warner(aTHX_ WARN_OVERFLOW,
"Integer overflow in %s number",
base);
} else
sv = NEWSV(92,0);
if (overflowed) {
dTHR;
- if (ckWARN(WARN_UNSAFE) && (double) n > 4294967295.0)
- Perl_warner(aTHX_ WARN_UNSAFE,
+ if (ckWARN(WARN_PORTABLE) && n > 4294967295.0)
+ Perl_warner(aTHX_ WARN_PORTABLE,
"%s number > %s non-portable",
Base, max);
sv_setnv(sv, n);
}
else {
+#if UVSIZE > 4
dTHR;
- if (ckWARN(WARN_UNSAFE) && u > 4294967295)
- Perl_warner(aTHX_ WARN_UNSAFE,
+ if (ckWARN(WARN_PORTABLE) && u > 0xffffffff)
+ Perl_warner(aTHX_ WARN_PORTABLE,
"%s number > %s non-portable",
Base, max);
+#endif
sv_setuv(sv, u);
}
- if ( PL_hints & HINT_NEW_BINARY)
+ if (PL_hints & HINT_NEW_BINARY)
sv = new_constant(start, s - start, "binary", sv, Nullsv, NULL);
}
break;
sv_setiv(sv, tryiv);
else
sv_setnv(sv, value);
- if ( floatit ? (PL_hints & HINT_NEW_FLOAT) : (PL_hints & HINT_NEW_INTEGER) )
+ if ( floatit ? (PL_hints & HINT_NEW_FLOAT) :
+ (PL_hints & HINT_NEW_INTEGER) )
sv = new_constant(PL_tokenbuf, d - PL_tokenbuf,
- (floatit ? "float" : "integer"), sv, Nullsv, NULL);
+ (floatit ? "float" : "integer"),
+ sv, Nullsv, NULL);
break;
}
if (*s == '.' || *s == '}') {
/*SUPPRESS 530*/
#ifdef PERL_STRICT_CR
- for (t = s+1;*t == ' ' || *t == '\t'; t++) ;
+ for (t = s+1;SPACE_OR_TAB(*t); t++) ;
#else
- for (t = s+1;*t == ' ' || *t == '\t' || *t == '\r'; t++) ;
+ for (t = s+1;SPACE_OR_TAB(*t) || *t == '\r'; t++) ;
#endif
if (*t == '\n' || t == PL_bufend)
break;
Perl_yywarn(pTHX_ char *s)
{
dTHR;
- --PL_error_count;
PL_in_eval |= EVAL_WARNONLY;
yyerror(s);
PL_in_eval &= ~EVAL_WARNONLY;
where = SvPVX(where_sv);
}
msg = sv_2mortal(newSVpv(s, 0));
- Perl_sv_catpvf(aTHX_ msg, " at %_ line %ld, ",
- GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
+ Perl_sv_catpvf(aTHX_ msg, " at %_ line %"IVdf", ",
+ CopFILESV(PL_curcop), (IV)PL_curcop->cop_line);
if (context)
Perl_sv_catpvf(aTHX_ msg, "near \"%.*s\"\n", contlen, context);
else
Perl_sv_catpvf(aTHX_ msg, "%s\n", where);
- if (PL_multi_start < PL_multi_end && (U32)(PL_curcop->cop_line - PL_multi_end) <= 1) {
- Perl_sv_catpvf(aTHX_ msg,
- " (Might be a runaway multi-line %c%c string starting on line %ld)\n",
- (int)PL_multi_open,(int)PL_multi_close,(long)PL_multi_start);
+ if (PL_multi_start < PL_multi_end &&
+ (U32)(PL_curcop->cop_line - PL_multi_end) <= 1) {
+ Perl_sv_catpvf(aTHX_ msg,
+ " (Might be a runaway multi-line %c%c string starting on line %"IVdf")\n",
+ (int)PL_multi_open,(int)PL_multi_close,(IV)PL_multi_start);
PL_multi_end = 0;
}
if (PL_in_eval & EVAL_WARNONLY)
Perl_warn(aTHX_ "%_", msg);
- else if (PL_in_eval)
- sv_catsv(ERRSV, msg);
else
- PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
- if (++PL_error_count >= 10)
- Perl_croak(aTHX_ "%_ has too many errors.\n", GvSV(PL_curcop->cop_filegv));
+ qerror(msg);
+ if (PL_error_count >= 10)
+ Perl_croak(aTHX_ "%_ has too many errors.\n", CopFILESV(PL_curcop));
PL_in_my = 0;
PL_in_my_stash = Nullhv;
return 0;
#ifdef PERL_OBJECT
-#define NO_XSLOCKS
#include "XSUB.h"
#endif