File Coverage

hax/newOP_CUSTOM.c.inc
Criterion Covered Total %
statement 2 2 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 2 2 100.0


line stmt bran cond sub pod time code
1             /* vi: set ft=c : */
2              
3             /* Before perl 5.22 under -DDEBUGGING, various new*OP() functions throw assert
4             * failures on OP_CUSTOM.
5             * https://rt.cpan.org/Ticket/Display.html?id=128562
6             */
7              
8             #define newOP_CUSTOM(func, flags) S_newOP_CUSTOM(aTHX_ func, flags)
9             #define newUNOP_CUSTOM(func, flags, first) S_newUNOP_CUSTOM(aTHX_ func, flags, first)
10             #define newUNOP_AUX_CUSTOM(func, flags, first, aux) S_newUNOP_AUX_CUSTOM(aTHX_ func, flags, first, aux)
11             #define newSVOP_CUSTOM(func, flags, sv) S_newSVOP_CUSTOM(aTHX_ func, flags, sv)
12             #define newBINOP_CUSTOM(func, flags, first, last) S_newBINOP_CUSTOM(aTHX_ func, flags, first, last)
13             #define newLISTOP_CUSTOM(func, flags, first, last) S_newLISTOP_CUSTOM(aTHX_ func, flags, first, last)
14             #define newLOGOP_CUSTOM(func, flags, first, other) S_newLOGOP_CUSTOM(aTHX_ func, flags, first, other)
15              
16             static OP *S_newOP_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags)
17             {
18             OP *op = newOP(OP_CUSTOM, flags);
19             op->op_ppaddr = func;
20             return op;
21             }
22              
23             static OP *S_newUNOP_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags, OP *first)
24             {
25             UNOP *unop;
26             #if HAVE_PERL_VERSION(5,22,0)
27             unop = (UNOP *)newUNOP(OP_CUSTOM, flags, first);
28             #else
29             NewOp(1101, unop, 1, UNOP);
30             unop->op_type = (OPCODE)OP_CUSTOM;
31             unop->op_first = first;
32             unop->op_flags = (U8)(flags | OPf_KIDS);
33             unop->op_private = (U8)(1 | (flags >> 8));
34             #endif
35             unop->op_ppaddr = func;
36             return (OP *)unop;
37             }
38              
39             static OP *S_newUNOP_AUX_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags, OP *first, UNOP_AUX_item *aux)
40             {
41             UNOP_AUX *unop;
42             #if HAVE_PERL_VERSION(5,22,0)
43 2           unop = (UNOP_AUX *)newUNOP_AUX(OP_CUSTOM, flags, first, aux);
44             #else
45             croak("TODO: create newUNOP_AUX_CUSTOM");
46             #endif
47 2           unop->op_ppaddr = func;
48             return (OP *)unop;
49             }
50              
51             static OP *S_newSVOP_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags, SV *sv)
52             {
53             SVOP *svop;
54             #if HAVE_PERL_VERSION(5,22,0)
55             svop = (SVOP *)newSVOP(OP_CUSTOM, flags, sv);
56             #else
57             NewOp(1101, svop, 1, SVOP);
58             svop->op_type = (OPCODE)OP_CUSTOM;
59             svop->op_sv = sv;
60             svop->op_next = (OP *)svop;
61             svop->op_flags = 0;
62             svop->op_private = 0;
63             #endif
64             svop->op_ppaddr = func;
65             return (OP *)svop;
66             }
67              
68             static OP *S_newBINOP_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags, OP *first, OP *last)
69             {
70             BINOP *binop;
71             #if HAVE_PERL_VERSION(5,22,0)
72             binop = (BINOP *)newBINOP(OP_CUSTOM, flags, first, last);
73             #else
74             NewOp(1101, binop, 1, BINOP);
75             binop->op_type = (OPCODE)OP_CUSTOM;
76             binop->op_first = first;
77             first->op_sibling = last;
78             binop->op_last = last;
79             binop->op_flags = (U8)(flags | OPf_KIDS);
80             binop->op_private = (U8)(2 | (flags >> 8));
81             #endif
82             binop->op_ppaddr = func;
83             return (OP *)binop;
84             }
85              
86             static OP *S_newLISTOP_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags, OP *first, OP *last)
87             {
88             LISTOP *listop;
89             #if HAVE_PERL_VERSION(5,22,0)
90             listop = (LISTOP *)newLISTOP(OP_CUSTOM, flags, first, last);
91             #else
92             NewOp(1101, listop, 1, LISTOP);
93             listop->op_type = (OPCODE)OP_CUSTOM;
94             listop->op_first = first;
95             if(first)
96             first->op_sibling = last;
97             listop->op_last = last;
98             listop->op_flags = (U8)(flags | OPf_KIDS);
99             if(last)
100             listop->op_private = (U8)(2 | (flags >> 8));
101             else if(first)
102             listop->op_private = (U8)(1 | (flags >> 8));
103             else
104             listop->op_private = (U8)(flags >> 8);
105             #endif
106             listop->op_ppaddr = func;
107             return (OP *)listop;
108             }
109              
110             static OP *S_newLOGOP_CUSTOM(pTHX_ OP *(*func)(pTHX), U32 flags, OP *first, OP *other)
111             {
112             OP *o;
113             #if HAVE_PERL_VERSION(5,22,0)
114             o = newLOGOP(OP_CUSTOM, flags, first, other);
115             #else
116             /* Parts of this code copypasted from perl 5.20.0's op.c S_new_logop()
117             */
118             LOGOP *logop;
119              
120             first = op_contextualize(first, G_SCALAR);
121              
122             NewOp(1101, logop, 1, LOGOP);
123              
124             logop->op_type = (OPCODE)OP_CUSTOM;
125             logop->op_ppaddr = NULL; /* Because caller only overrides it anyway */
126             logop->op_first = first;
127             logop->op_flags = (U8)(flags | OPf_KIDS);
128             logop->op_other = LINKLIST(other);
129             logop->op_private = (U8)(1 | (flags >> 8));
130              
131             /* Link in postfix order */
132             logop->op_next = LINKLIST(first);
133             first->op_next = (OP *)logop;
134             first->op_sibling = other;
135              
136             /* No CHECKOP for OP_CUSTOM */
137             o = newUNOP(OP_NULL, 0, (OP *)logop);
138             other->op_next = o;
139             #endif
140              
141             /* the returned op is actually an UNOP that's either NULL or NOT; the real
142             * logop is the op_next of it
143             */
144             cUNOPx(o)->op_first->op_ppaddr = func;
145              
146             return o;
147             }