+static void xsh_peep_rec(pTHX_ OP *o, ptable *seen) {
+ for (; o; o = o->op_next) {
+ if (xsh_peep_seen(o, seen))
+ break;
+
+ switch (o->op_type) {
+ case OP_PADSV:
+ if (o->op_ppaddr != lt_pp_padsv && o->op_private & OPpLVAL_INTRO) {
+ lt_op_padxv_info *oi;
+ XSH_LOCK(<_op_map_mutex);
+ oi = ptable_fetch(lt_op_padxv_map, o);
+ if (oi) {
+ oi->old_pp = o->op_ppaddr;
+ o->op_ppaddr = lt_pp_padsv;
+ }
+ XSH_UNLOCK(<_op_map_mutex);
+ }
+ break;
+#if XSH_HAS_PERL(5, 17, 6)
+ case OP_PADRANGE:
+ /* We deal with special padrange ops later, in the aassign op they belong
+ * to. */
+ if (o->op_ppaddr != lt_pp_padrange && o->op_private & OPpLVAL_INTRO
+ && !(o->op_flags & OPf_SPECIAL)) {
+ /* A padrange op is guaranteed to have previously been a pushmark.
+ * Moreover, for non-special padrange ops (i.e. that aren't for
+ * my (...) = @_), the first original padxv is its sibling or nephew.
+ */
+ OP *kid = OpSIBLING(o);
+ if (kid->op_type == OP_NULL && kid->op_flags & OPf_KIDS) {
+ kid = kUNOP->op_first;
+ if (kid->op_type == OP_NULL)
+ kid = OpSIBLING(kid);
+ }
+ lt_maybe_padrange_setup(o, kid);
+ }
+ break;
+ case OP_AASSIGN: {
+ OP *op;
+ if (cBINOPo->op_first && cBINOPo->op_first->op_flags & OPf_KIDS
+ && (op = cUNOPx(cBINOPo->op_first)->op_first)
+ && op->op_type == OP_PADRANGE
+ && op->op_ppaddr != lt_pp_padrange
+ && op->op_private & OPpLVAL_INTRO
+ && op->op_flags & OPf_SPECIAL) {
+ const OP *start = cUNOPx(cBINOPo->op_last)->op_first;
+ if (start->op_type == OP_PUSHMARK)
+ start = OpSIBLING(start);
+ lt_maybe_padrange_setup(op, start);
+ }
+ break;
+ }
+#endif
+ default:
+ xsh_peep_maybe_recurse(o, seen);
+ break;
+ }
+ }
+}