File Coverage

hax/newOP_CUSTOM.c.inc
Criterion Covered Total %
statement 4 28 14.2
branch n/a
condition n/a
subroutine n/a
pod n/a
total 4 28 14.2


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