+ parser->parsed_sub = 1;
+ }
+ | SUB subname startsub
+ {
+ if ($2->op_type == OP_CONST) {
+ const char *const name =
+ SvPV_nolen_const(((SVOP*)$2)->op_sv);
+ if (strEQ(name, "BEGIN") || strEQ(name, "END")
+ || strEQ(name, "INIT") || strEQ(name, "CHECK")
+ || strEQ(name, "UNITCHECK"))
+ CvSPECIAL_on(PL_compcv);
+ }
+ else
+ /* State subs inside anonymous subs need to be
+ clonable themselves. */
+ if (CvANON(CvOUTSIDE(PL_compcv))
+ || CvCLONE(CvOUTSIDE(PL_compcv))
+ || !PadnameIsSTATE(PadlistNAMESARRAY(CvPADLIST(
+ CvOUTSIDE(PL_compcv)
+ ))[$2->op_targ]))
+ CvCLONE_on(PL_compcv);
+ parser->in_my = 0;
+ parser->in_my_stash = NULL;
+ }
+ proto subattrlist optsubbody
+ {
+ SvREFCNT_inc_simple_void(PL_compcv);
+ $2->op_type == OP_CONST
+ ? newATTRSUB($3, $2, $5, $6, $7)
+ : newMYSUB($3, $2, $5, $6, $7)
+ ;
+ $$ = (OP*)NULL;
+ intro_my();
+ parser->parsed_sub = 1;
+ }
+ | SUB subname startsub
+ {
+ if ($2->op_type == OP_CONST) {
+ const char *const name =
+ SvPV_nolen_const(((SVOP*)$2)->op_sv);
+ if (strEQ(name, "BEGIN") || strEQ(name, "END")
+ || strEQ(name, "INIT") || strEQ(name, "CHECK")
+ || strEQ(name, "UNITCHECK"))
+ CvSPECIAL_on(PL_compcv);
+ }
+ else
+ /* State subs inside anonymous subs need to be
+ clonable themselves. */
+ if (CvANON(CvOUTSIDE(PL_compcv))
+ || CvCLONE(CvOUTSIDE(PL_compcv))
+ || !PadnameIsSTATE(PadlistNAMESARRAY(CvPADLIST(
+ CvOUTSIDE(PL_compcv)
+ ))[$2->op_targ]))
+ CvCLONE_on(PL_compcv);
+ parser->in_my = 0;
+ parser->in_my_stash = NULL;
+ }
+ remember subsignature subattrlist '{' stmtseq '}'
+ {
+ OP *body;
+ if (parser->copline > (line_t)$8)
+ parser->copline = (line_t)$8;
+ body = block_end($5,
+ op_append_list(OP_LINESEQ, $6, $9));
+
+ SvREFCNT_inc_simple_void(PL_compcv);
+ $2->op_type == OP_CONST
+ ? newATTRSUB($3, $2, NULL, $7, body)
+ : newMYSUB($3, $2, NULL, $7, body)
+ ;
+ $$ = (OP*)NULL;
+ intro_my();
+ parser->parsed_sub = 1;
+ }
+ | PACKAGE BAREWORD BAREWORD ';'
+ {
+ package($3);
+ if ($2)
+ package_version($2);
+ $$ = (OP*)NULL;
+ }
+ | USE startsub
+ { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
+ BAREWORD BAREWORD optlistexpr ';'
+ {
+ SvREFCNT_inc_simple_void(PL_compcv);
+ utilize($1, $2, $4, $5, $6);
+ parser->parsed_sub = 1;
+ $$ = (OP*)NULL;
+ }
+ | IF '(' remember mexpr ')' mblock else
+ {
+ $$ = block_end($3,
+ newCONDOP(0, $4, op_scope($6), $7));
+ parser->copline = (line_t)$1;
+ }
+ | UNLESS '(' remember mexpr ')' mblock else
+ {
+ $$ = block_end($3,
+ newCONDOP(0, $4, $7, op_scope($6)));
+ parser->copline = (line_t)$1;
+ }
+ | GIVEN '(' remember mexpr ')' mblock
+ {
+ $$ = block_end($3, newGIVENOP($4, op_scope($6), 0));
+ parser->copline = (line_t)$1;
+ }
+ | WHEN '(' remember mexpr ')' mblock
+ { $$ = block_end($3, newWHENOP($4, op_scope($6))); }
+ | DEFAULT block
+ { $$ = newWHENOP(0, op_scope($2)); }
+ | WHILE '(' remember texpr ')' mintro mblock cont
+ {
+ $$ = block_end($3,
+ newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
+ $4, $7, $8, $6));
+ parser->copline = (line_t)$1;
+ }
+ | UNTIL '(' remember iexpr ')' mintro mblock cont
+ {
+ $$ = block_end($3,
+ newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
+ $4, $7, $8, $6));
+ parser->copline = (line_t)$1;
+ }
+ | FOR '(' remember mnexpr ';'
+ { parser->expect = XTERM; }
+ texpr ';'
+ { parser->expect = XTERM; }
+ mintro mnexpr ')'
+ mblock
+ {
+ OP *initop = $4;
+ OP *forop = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
+ scalar($7), $13, $11, $10);
+ if (initop) {
+ forop = op_prepend_elem(OP_LINESEQ, initop,
+ op_append_elem(OP_LINESEQ,
+ newOP(OP_UNSTACK, OPf_SPECIAL),
+ forop));
+ }
+ PL_hints |= HINT_BLOCK_SCOPE;
+ $$ = block_end($3, forop);
+ parser->copline = (line_t)$1;
+ }
+ | FOR MY remember my_scalar '(' mexpr ')' mblock cont
+ {
+ $$ = block_end($3, newFOROP(0, $4, $6, $8, $9));
+ parser->copline = (line_t)$1;
+ }
+ | FOR scalar '(' remember mexpr ')' mblock cont
+ {
+ $$ = block_end($4, newFOROP(0,
+ op_lvalue($2, OP_ENTERLOOP), $5, $7, $8));
+ parser->copline = (line_t)$1;
+ }
+ | FOR my_refgen remember my_var
+ { parser->in_my = 0; $<opval>$ = my($4); }
+ '(' mexpr ')' mblock cont
+ {
+ $$ = block_end(
+ $3,
+ newFOROP(0,
+ op_lvalue(
+ newUNOP(OP_REFGEN, 0,
+ $<opval>5),
+ OP_ENTERLOOP),
+ $7, $9, $10)
+ );
+ parser->copline = (line_t)$1;
+ }
+ | FOR REFGEN refgen_topic '(' remember mexpr ')' mblock cont
+ {
+ $$ = block_end($5, newFOROP(
+ 0, op_lvalue(newUNOP(OP_REFGEN, 0,
+ $3),
+ OP_ENTERLOOP), $6, $8, $9));
+ parser->copline = (line_t)$1;
+ }
+ | FOR '(' remember mexpr ')' mblock cont
+ {
+ $$ = block_end($3,
+ newFOROP(0, (OP*)NULL, $4, $6, $7));
+ parser->copline = (line_t)$1;
+ }
+ | block cont
+ {
+ /* a block is a loop that happens once */
+ $$ = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
+ (OP*)NULL, $1, $2, 0);
+ }
+ | PACKAGE BAREWORD BAREWORD '{' remember
+ {
+ package($3);
+ if ($2) {
+ package_version($2);