Commit | Line | Data |
db81d362 |
1 | /* |
2 | Copyright 2012 Lukas Mai. |
3 | |
4 | This program is free software; you can redistribute it and/or modify it |
5 | under the terms of either: the GNU General Public License as published |
6 | by the Free Software Foundation; or the Artistic License. |
7 | |
8 | See http://dev.perl.org/licenses/ for more information. |
9 | */ |
10 | |
11 | #ifdef __GNUC__ |
12 | #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ >= 5 |
13 | #define PRAGMA_GCC_(X) _Pragma(#X) |
14 | #define PRAGMA_GCC(X) PRAGMA_GCC_(GCC X) |
15 | #endif |
16 | #endif |
17 | |
18 | #ifndef PRAGMA_GCC |
19 | #define PRAGMA_GCC(X) |
20 | #endif |
21 | |
22 | #ifdef DEVEL |
23 | #define WARNINGS_RESET PRAGMA_GCC(diagnostic pop) |
24 | #define WARNINGS_ENABLEW(X) PRAGMA_GCC(diagnostic warning #X) |
25 | #define WARNINGS_ENABLE \ |
26 | WARNINGS_ENABLEW(-Wall) \ |
27 | WARNINGS_ENABLEW(-Wextra) \ |
28 | WARNINGS_ENABLEW(-Wundef) \ |
c3e72f35 |
29 | /* WARNINGS_ENABLEW(-Wshadow) :-( */ \ |
db81d362 |
30 | WARNINGS_ENABLEW(-Wbad-function-cast) \ |
31 | WARNINGS_ENABLEW(-Wcast-align) \ |
32 | WARNINGS_ENABLEW(-Wwrite-strings) \ |
33 | /* WARNINGS_ENABLEW(-Wnested-externs) wtf? */ \ |
34 | WARNINGS_ENABLEW(-Wstrict-prototypes) \ |
35 | WARNINGS_ENABLEW(-Wmissing-prototypes) \ |
36 | WARNINGS_ENABLEW(-Winline) \ |
37 | WARNINGS_ENABLEW(-Wdisabled-optimization) |
38 | |
39 | #else |
40 | #define WARNINGS_RESET |
1bc47886 |
41 | #define WARNINGS_ENABLE |
db81d362 |
42 | #endif |
43 | |
44 | |
7dd35535 |
45 | #define PERL_NO_GET_CONTEXT |
db81d362 |
46 | #include "EXTERN.h" |
47 | #include "perl.h" |
48 | #include "XSUB.h" |
49 | |
50 | #include <string.h> |
51 | |
52 | WARNINGS_ENABLE |
53 | |
54 | #define MY_PKG "Function::Parameters" |
55 | |
56 | #define HINTK_KEYWORDS MY_PKG "/keywords" |
57 | #define HINTK_NAME_ MY_PKG "/name:" |
58 | #define HINTK_SHIFT_ MY_PKG "/shift:" |
b72eb6ee |
59 | #define HINTK_ATTRS_ MY_PKG "/attrs:" |
db81d362 |
60 | |
7dd35535 |
61 | #define HAVE_PERL_VERSION(R, V, S) \ |
62 | (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) |
63 | |
de013990 |
64 | #if HAVE_PERL_VERSION(5, 16, 0) |
65 | #define IF_HAVE_PERL_5_16(YES, NO) YES |
66 | #else |
67 | #define IF_HAVE_PERL_5_16(YES, NO) NO |
68 | #endif |
69 | |
db81d362 |
70 | typedef struct { |
71 | enum { |
72 | FLAG_NAME_OPTIONAL = 1, |
73 | FLAG_NAME_REQUIRED, |
74 | FLAG_NAME_PROHIBITED |
75 | } name; |
b72eb6ee |
76 | SV *shift; |
77 | SV *attrs; |
db81d362 |
78 | } Spec; |
79 | |
80 | static int (*next_keyword_plugin)(pTHX_ char *, STRLEN, OP **); |
81 | |
7dd35535 |
82 | static int kw_flags(pTHX_ const char *kw_ptr, STRLEN kw_len, Spec *spec) { |
db81d362 |
83 | HV *hints; |
84 | SV *sv, **psv; |
85 | const char *p, *kw_active; |
86 | STRLEN kw_active_len; |
87 | |
88 | spec->name = 0; |
b72eb6ee |
89 | spec->shift = sv_2mortal(newSVpvs("")); |
90 | spec->attrs = sv_2mortal(newSVpvs("")); |
db81d362 |
91 | |
92 | if (!(hints = GvHV(PL_hintgv))) { |
93 | return FALSE; |
94 | } |
95 | if (!(psv = hv_fetchs(hints, HINTK_KEYWORDS, 0))) { |
96 | return FALSE; |
97 | } |
98 | sv = *psv; |
99 | kw_active = SvPV(sv, kw_active_len); |
100 | if (kw_active_len <= kw_len) { |
101 | return FALSE; |
102 | } |
e88490f6 |
103 | for ( |
104 | p = kw_active; |
105 | (p = strchr(p, *kw_ptr)) && |
106 | p < kw_active + kw_active_len - kw_len; |
107 | p++ |
108 | ) { |
db81d362 |
109 | if ( |
110 | (p == kw_active || p[-1] == ' ') && |
111 | p[kw_len] == ' ' && |
112 | memcmp(kw_ptr, p, kw_len) == 0 |
113 | ) { |
b72eb6ee |
114 | |
d970c3e7 |
115 | #define FETCH_HINTK_INTO(NAME, PTR, LEN, X) STMT_START { \ |
b72eb6ee |
116 | const char *fk_ptr_; \ |
117 | STRLEN fk_len_; \ |
118 | SV *fk_sv_; \ |
119 | fk_sv_ = sv_2mortal(newSVpvs(HINTK_ ## NAME)); \ |
120 | sv_catpvn(fk_sv_, PTR, LEN); \ |
121 | fk_ptr_ = SvPV(fk_sv_, fk_len_); \ |
122 | if (!((X) = hv_fetch(hints, fk_ptr_, fk_len_, 0))) { \ |
123 | croak("%s: internal error: $^H{'%.*s'} not set", MY_PKG, (int)fk_len_, fk_ptr_); \ |
124 | } \ |
d970c3e7 |
125 | } STMT_END |
b72eb6ee |
126 | |
127 | FETCH_HINTK_INTO(NAME_, kw_ptr, kw_len, psv); |
db81d362 |
128 | spec->name = SvIV(*psv); |
129 | |
b72eb6ee |
130 | FETCH_HINTK_INTO(SHIFT_, kw_ptr, kw_len, psv); |
131 | SvSetSV(spec->shift, *psv); |
db81d362 |
132 | |
b72eb6ee |
133 | FETCH_HINTK_INTO(ATTRS_, kw_ptr, kw_len, psv); |
134 | SvSetSV(spec->attrs, *psv); |
135 | |
136 | #undef FETCH_HINTK_INTO |
db81d362 |
137 | return TRUE; |
138 | } |
139 | } |
140 | return FALSE; |
141 | } |
142 | |
143 | |
144 | #include "toke_on_crack.c.inc" |
145 | |
146 | |
311ced6f |
147 | static void free_ptr_op(pTHX_ void *vp) { |
c311cef3 |
148 | OP **pp = vp; |
149 | op_free(*pp); |
150 | Safefree(pp); |
151 | } |
152 | |
59016bfb |
153 | #define sv_eq_pvs(SV, S) my_sv_eq_pvn(aTHX_ SV, "" S "", sizeof (S) - 1) |
c311cef3 |
154 | |
59016bfb |
155 | static int my_sv_eq_pvn(pTHX_ SV *sv, const char *p, STRLEN n) { |
c311cef3 |
156 | STRLEN sv_len; |
157 | const char *sv_p = SvPV(sv, sv_len); |
59016bfb |
158 | return memcmp(sv_p, p, n) == 0; |
c311cef3 |
159 | } |
160 | |
161 | |
162 | #include "padop_on_crack.c.inc" |
163 | |
164 | |
165 | #if 0 |
166 | static PADOFFSET pad_add_my_sv(SV *name) { |
167 | PADOFFSET offset; |
168 | SV *namesv, *myvar; |
169 | char *p; |
170 | STRLEN len; |
171 | |
172 | p = SvPV(name, len); |
173 | myvar = *av_fetch(PL_comppad, AvFILLp(PL_comppad) + 1, 1); |
174 | offset = AvFILLp(PL_comppad); |
175 | SvPADMY_on(myvar); |
176 | if (*p == '@') { |
177 | SvUPGRADE(myvar, SVt_PVAV); |
178 | } else if (*p == '%') { |
179 | SvUPGRADE(myvar, SVt_PVHV); |
180 | } |
181 | PL_curpad = AvARRAY(PL_comppad); |
182 | namesv = newSV_type(SVt_PVMG); |
183 | sv_setpvn(namesv, p, len); |
184 | COP_SEQ_RANGE_LOW_set(namesv, PL_cop_seqmax); |
185 | COP_SEQ_RANGE_HIGH_set(namesv, PERL_PADSEQ_INTRO); |
186 | PL_cop_seqmax++; |
187 | av_store(PL_comppad_name, offset, namesv); |
188 | return offset; |
189 | } |
190 | #endif |
191 | |
192 | enum { |
193 | MY_ATTR_LVALUE = 0x01, |
194 | MY_ATTR_METHOD = 0x02, |
195 | MY_ATTR_SPECIAL = 0x04 |
196 | }; |
197 | |
7dd35535 |
198 | static int parse_fun(pTHX_ OP **pop, const char *keyword_ptr, STRLEN keyword_len, const Spec *spec) { |
c311cef3 |
199 | SV *declarator; |
200 | I32 floor_ix; |
201 | SV *saw_name; |
202 | AV *params; |
203 | SV *proto; |
204 | OP **attrs_sentinel, *body; |
205 | unsigned builtin_attrs; |
db81d362 |
206 | STRLEN len; |
207 | char *s; |
208 | I32 c; |
209 | |
db81d362 |
210 | declarator = sv_2mortal(newSVpvn(keyword_ptr, keyword_len)); |
db81d362 |
211 | |
db81d362 |
212 | lex_read_space(0); |
213 | |
c311cef3 |
214 | builtin_attrs = 0; |
215 | |
db81d362 |
216 | /* function name */ |
c311cef3 |
217 | saw_name = NULL; |
db81d362 |
218 | s = PL_parser->bufptr; |
7dd35535 |
219 | if (spec->name != FLAG_NAME_PROHIBITED && (len = S_scan_word(aTHX_ s, TRUE))) { |
c311cef3 |
220 | saw_name = sv_2mortal(newSVpvn_flags(s, len, PARSING_UTF ? SVf_UTF8 : 0)); |
221 | |
222 | if (PL_parser->expect != XSTATE) { |
223 | /* bail out early so we don't predeclare $saw_name */ |
224 | croak("In %"SVf": I was expecting a function body, not \"%"SVf"\"", SVfARG(declarator), SVfARG(saw_name)); |
225 | } |
226 | |
db81d362 |
227 | sv_catpvs(declarator, " "); |
c311cef3 |
228 | sv_catsv(declarator, saw_name); |
229 | |
230 | if ( |
231 | sv_eq_pvs(saw_name, "BEGIN") || |
232 | sv_eq_pvs(saw_name, "END") || |
233 | sv_eq_pvs(saw_name, "INIT") || |
234 | sv_eq_pvs(saw_name, "CHECK") || |
235 | sv_eq_pvs(saw_name, "UNITCHECK") |
236 | ) { |
237 | builtin_attrs |= MY_ATTR_SPECIAL; |
238 | } |
239 | |
db81d362 |
240 | lex_read_to(s + len); |
241 | lex_read_space(0); |
db81d362 |
242 | } else if (spec->name == FLAG_NAME_REQUIRED) { |
243 | croak("I was expecting a function name, not \"%.*s\"", (int)(PL_parser->bufend - s), s); |
244 | } else { |
245 | sv_catpvs(declarator, " (anon)"); |
246 | } |
247 | |
c311cef3 |
248 | floor_ix = start_subparse(FALSE, saw_name ? 0 : CVf_ANON); |
249 | SAVEFREESV(PL_compcv); |
250 | |
db81d362 |
251 | /* parameters */ |
c311cef3 |
252 | params = NULL; |
db81d362 |
253 | c = lex_peek_unichar(0); |
254 | if (c == '(') { |
255 | SV *saw_slurpy = NULL; |
256 | |
257 | lex_read_unichar(0); |
258 | lex_read_space(0); |
259 | |
c311cef3 |
260 | params = newAV(); |
261 | sv_2mortal((SV *)params); |
262 | |
db81d362 |
263 | for (;;) { |
264 | c = lex_peek_unichar(0); |
f5cc9bdd |
265 | if (c == '$' || c == '@' || c == '%') { |
c311cef3 |
266 | SV *param; |
267 | |
db81d362 |
268 | lex_read_unichar(0); |
269 | lex_read_space(0); |
270 | |
271 | s = PL_parser->bufptr; |
7dd35535 |
272 | if (!(len = S_scan_word(aTHX_ s, FALSE))) { |
85bc3fbd |
273 | croak("In %"SVf": missing identifier", SVfARG(declarator)); |
db81d362 |
274 | } |
c311cef3 |
275 | param = sv_2mortal(newSVpvf("%c%.*s", (int)c, (int)len, s)); |
db81d362 |
276 | if (saw_slurpy) { |
c311cef3 |
277 | croak("In %"SVf": I was expecting \")\" after \"%"SVf"\", not \"%"SVf"\"", SVfARG(declarator), SVfARG(saw_slurpy), SVfARG(param)); |
db81d362 |
278 | } |
279 | if (c != '$') { |
c311cef3 |
280 | saw_slurpy = param; |
db81d362 |
281 | } |
c311cef3 |
282 | av_push(params, SvREFCNT_inc_simple_NN(param)); |
db81d362 |
283 | lex_read_to(s + len); |
284 | lex_read_space(0); |
285 | |
286 | c = lex_peek_unichar(0); |
287 | if (c == ',') { |
288 | lex_read_unichar(0); |
289 | lex_read_space(0); |
290 | continue; |
291 | } |
292 | } |
293 | |
294 | if (c == ')') { |
295 | lex_read_unichar(0); |
296 | lex_read_space(0); |
297 | break; |
298 | } |
299 | |
300 | if (c == -1) { |
85bc3fbd |
301 | croak("In %"SVf": unexpected EOF in parameter list", SVfARG(declarator)); |
db81d362 |
302 | } |
85bc3fbd |
303 | croak("In %"SVf": unexpected '%c' in parameter list", SVfARG(declarator), (int)c); |
db81d362 |
304 | } |
305 | } |
306 | |
307 | /* prototype */ |
c311cef3 |
308 | proto = NULL; |
db81d362 |
309 | c = lex_peek_unichar(0); |
310 | if (c == ':') { |
311 | lex_read_unichar(0); |
312 | lex_read_space(0); |
313 | |
314 | c = lex_peek_unichar(0); |
315 | if (c != '(') { |
c311cef3 |
316 | lex_stuff_pvs(":", 0); |
317 | c = ':'; |
db81d362 |
318 | } else { |
c311cef3 |
319 | proto = sv_2mortal(newSVpvs("")); |
320 | if (!S_scan_str(aTHX_ proto, FALSE, FALSE)) { |
f34187b8 |
321 | croak("In %"SVf": prototype not terminated", SVfARG(declarator)); |
db81d362 |
322 | } |
311ced6f |
323 | S_check_prototype(aTHX_ declarator, proto); |
db81d362 |
324 | lex_read_space(0); |
c311cef3 |
325 | c = lex_peek_unichar(0); |
db81d362 |
326 | } |
327 | } |
328 | |
c311cef3 |
329 | /* surprise predeclaration! */ |
db81d362 |
330 | if (saw_name) { |
c311cef3 |
331 | /* 'sub NAME (PROTO);' to make name/proto known to perl before it |
332 | starts parsing the body */ |
333 | SvREFCNT_inc_simple_void(PL_compcv); |
334 | |
335 | newATTRSUB( |
336 | floor_ix, |
337 | newSVOP(OP_CONST, 0, SvREFCNT_inc_simple_NN(saw_name)), |
338 | proto ? newSVOP(OP_CONST, 0, SvREFCNT_inc_simple_NN(proto)) : NULL, |
339 | NULL, |
340 | NULL |
341 | ); |
342 | |
343 | floor_ix = start_subparse(FALSE, 0); |
344 | SAVEFREESV(PL_compcv); |
db81d362 |
345 | } |
346 | |
c311cef3 |
347 | |
db81d362 |
348 | /* attributes */ |
c311cef3 |
349 | Newx(attrs_sentinel, 1, OP *); |
350 | *attrs_sentinel = NULL; |
311ced6f |
351 | SAVEDESTRUCTOR_X(free_ptr_op, attrs_sentinel); |
c311cef3 |
352 | |
353 | if (c == ':' || c == '{') { |
354 | |
355 | /* kludge default attributes in */ |
356 | if (SvTRUE(spec->attrs) && SvPV_nolen(spec->attrs)[0] == ':') { |
357 | lex_stuff_sv(spec->attrs, 0); |
358 | c = ':'; |
359 | } |
b72eb6ee |
360 | |
db81d362 |
361 | if (c == ':') { |
db81d362 |
362 | lex_read_unichar(0); |
363 | lex_read_space(0); |
db81d362 |
364 | c = lex_peek_unichar(0); |
c311cef3 |
365 | |
366 | for (;;) { |
367 | SV *attr; |
368 | |
369 | s = PL_parser->bufptr; |
370 | if (!(len = S_scan_word(aTHX_ s, FALSE))) { |
371 | break; |
db81d362 |
372 | } |
c311cef3 |
373 | |
374 | attr = sv_2mortal(newSVpvn_flags(s, len, PARSING_UTF ? SVf_UTF8 : 0)); |
375 | |
376 | lex_read_to(s + len); |
db81d362 |
377 | lex_read_space(0); |
378 | c = lex_peek_unichar(0); |
c311cef3 |
379 | |
380 | if (c != '(') { |
381 | if (sv_eq_pvs(attr, "lvalue")) { |
382 | builtin_attrs |= MY_ATTR_LVALUE; |
383 | attr = NULL; |
384 | } else if (sv_eq_pvs(attr, "method")) { |
385 | builtin_attrs |= MY_ATTR_METHOD; |
386 | attr = NULL; |
387 | } |
388 | } else { |
389 | SV *sv = sv_2mortal(newSVpvs("")); |
390 | if (!S_scan_str(aTHX_ sv, TRUE, TRUE)) { |
391 | croak("In %"SVf": unterminated attribute parameter in attribute list", SVfARG(declarator)); |
392 | } |
393 | sv_catsv(attr, sv); |
394 | |
395 | lex_read_space(0); |
396 | c = lex_peek_unichar(0); |
397 | } |
398 | |
399 | if (attr) { |
400 | *attrs_sentinel = op_append_elem(OP_LIST, *attrs_sentinel, newSVOP(OP_CONST, 0, SvREFCNT_inc_simple_NN(attr))); |
401 | } |
402 | |
403 | if (c == ':') { |
404 | lex_read_unichar(0); |
405 | lex_read_space(0); |
406 | c = lex_peek_unichar(0); |
407 | } |
db81d362 |
408 | } |
409 | } |
410 | } |
411 | |
412 | /* body */ |
db81d362 |
413 | if (c != '{') { |
85bc3fbd |
414 | croak("In %"SVf": I was expecting a function body, not \"%c\"", SVfARG(declarator), (int)c); |
db81d362 |
415 | } |
c311cef3 |
416 | |
417 | if (builtin_attrs & MY_ATTR_LVALUE) { |
418 | CvLVALUE_on(PL_compcv); |
db81d362 |
419 | } |
c311cef3 |
420 | if (builtin_attrs & MY_ATTR_METHOD) { |
421 | CvMETHOD_on(PL_compcv); |
422 | } |
423 | if (builtin_attrs & MY_ATTR_SPECIAL) { |
424 | CvSPECIAL_on(PL_compcv); |
db81d362 |
425 | } |
426 | |
c311cef3 |
427 | /* munge */ |
428 | { |
429 | /* create outer block: '{' */ |
311ced6f |
430 | const int save_ix = S_block_start(aTHX_ TRUE); |
c311cef3 |
431 | OP *init = NULL; |
432 | |
433 | /* my $self = shift; */ |
434 | if (SvTRUE(spec->shift)) { |
435 | OP *const var = newOP(OP_PADSV, OPf_WANT_SCALAR | (OPpLVAL_INTRO << 8)); |
436 | var->op_targ = pad_add_name_sv(spec->shift, 0, NULL, NULL); |
437 | |
438 | init = newASSIGNOP(OPf_STACKED, var, 0, newOP(OP_SHIFT, 0)); |
439 | init = newSTATEOP(0, NULL, init); |
440 | } |
441 | |
442 | /* my (PARAMS) = @_; */ |
443 | if (params && av_len(params) > -1) { |
444 | SV *param; |
445 | OP *init_param, *left, *right; |
446 | |
447 | left = NULL; |
448 | while ((param = av_shift(params)) != &PL_sv_undef) { |
449 | OP *const var = newOP(OP_PADSV, OPf_WANT_LIST | (OPpLVAL_INTRO << 8)); |
450 | var->op_targ = pad_add_name_sv(param, 0, NULL, NULL); |
451 | SvREFCNT_dec(param); |
452 | left = op_append_elem(OP_LIST, left, var); |
453 | } |
454 | |
455 | left->op_flags |= OPf_PARENS; |
456 | right = newAVREF(newGVOP(OP_GV, 0, PL_defgv)); |
457 | init_param = newASSIGNOP(OPf_STACKED, left, 0, right); |
458 | init_param = newSTATEOP(0, NULL, init_param); |
459 | |
460 | init = op_append_list(OP_LINESEQ, init, init_param); |
461 | } |
462 | |
463 | /* add '();' to make function return nothing by default */ |
464 | /* (otherwise the invisible parameter initialization can "leak" into |
465 | the return value: fun ($x) {}->("asdf", 0) == 2) */ |
466 | if (init) { |
467 | init = op_append_list(OP_LINESEQ, init, newSTATEOP(0, NULL, newOP(OP_STUB, OPf_PARENS))); |
468 | } |
469 | |
470 | /* finally let perl parse the actual subroutine body */ |
471 | body = parse_block(0); |
472 | |
473 | body = op_append_list(OP_LINESEQ, init, body); |
474 | |
475 | /* close outer block: '}' */ |
311ced6f |
476 | S_block_end(aTHX_ save_ix, body); |
db81d362 |
477 | } |
478 | |
c311cef3 |
479 | /* it's go time. */ |
480 | { |
481 | OP *const attrs = *attrs_sentinel; |
482 | *attrs_sentinel = NULL; |
483 | SvREFCNT_inc_simple_void(PL_compcv); |
484 | |
485 | if (!saw_name) { |
486 | *pop = newANONATTRSUB( |
487 | floor_ix, |
488 | proto ? newSVOP(OP_CONST, 0, SvREFCNT_inc_simple_NN(proto)) : NULL, |
489 | attrs, |
490 | body |
491 | ); |
492 | return KEYWORD_PLUGIN_EXPR; |
493 | } |
494 | |
495 | newATTRSUB( |
496 | floor_ix, |
497 | newSVOP(OP_CONST, 0, SvREFCNT_inc_simple_NN(saw_name)), |
498 | proto ? newSVOP(OP_CONST, 0, SvREFCNT_inc_simple_NN(proto)) : NULL, |
499 | attrs, |
500 | body |
501 | ); |
502 | *pop = NULL; |
503 | return KEYWORD_PLUGIN_STMT; |
db81d362 |
504 | } |
db81d362 |
505 | } |
506 | |
507 | static int my_keyword_plugin(pTHX_ char *keyword_ptr, STRLEN keyword_len, OP **op_ptr) { |
508 | Spec spec; |
509 | int ret; |
510 | |
511 | SAVETMPS; |
512 | |
7dd35535 |
513 | if (kw_flags(aTHX_ keyword_ptr, keyword_len, &spec)) { |
514 | ret = parse_fun(aTHX_ op_ptr, keyword_ptr, keyword_len, &spec); |
db81d362 |
515 | } else { |
7dd35535 |
516 | ret = next_keyword_plugin(aTHX_ keyword_ptr, keyword_len, op_ptr); |
db81d362 |
517 | } |
518 | |
519 | FREETMPS; |
520 | |
521 | return ret; |
522 | } |
523 | |
524 | WARNINGS_RESET |
525 | |
526 | MODULE = Function::Parameters PACKAGE = Function::Parameters |
527 | PROTOTYPES: ENABLE |
528 | |
529 | BOOT: |
530 | WARNINGS_ENABLE { |
531 | HV *const stash = gv_stashpvs(MY_PKG, GV_ADD); |
426a4d69 |
532 | /**/ |
db81d362 |
533 | newCONSTSUB(stash, "FLAG_NAME_OPTIONAL", newSViv(FLAG_NAME_OPTIONAL)); |
534 | newCONSTSUB(stash, "FLAG_NAME_REQUIRED", newSViv(FLAG_NAME_REQUIRED)); |
535 | newCONSTSUB(stash, "FLAG_NAME_PROHIBITED", newSViv(FLAG_NAME_PROHIBITED)); |
536 | newCONSTSUB(stash, "HINTK_KEYWORDS", newSVpvs(HINTK_KEYWORDS)); |
537 | newCONSTSUB(stash, "HINTK_NAME_", newSVpvs(HINTK_NAME_)); |
538 | newCONSTSUB(stash, "HINTK_SHIFT_", newSVpvs(HINTK_SHIFT_)); |
b72eb6ee |
539 | newCONSTSUB(stash, "HINTK_ATTRS_", newSVpvs(HINTK_ATTRS_)); |
426a4d69 |
540 | /**/ |
db81d362 |
541 | next_keyword_plugin = PL_keyword_plugin; |
542 | PL_keyword_plugin = my_keyword_plugin; |
543 | } WARNINGS_RESET |