B::Hooks::OP::Check::Install::Files is not indexed
[p5sagit/Devel-Declare.git] / Declare.xs
1 #define PERL_NO_GET_CONTEXT 1
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5 #include "hook_op_check.h"
6 #undef printf
7 #include "stolen_chunk_of_toke.c"
8 #include <stdio.h>
9 #include <string.h>
10
11 #define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
12 #define PERL_DECIMAL_VERSION \
13   PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
14 #define PERL_VERSION_GE(r,v,s) \
15   (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
16
17 #ifndef Newx
18 # define Newx(v,n,t) New(0,v,n,t)
19 #endif /* !Newx */
20
21 #define DD_DEBUGf_UPDATED_LINESTR 1
22 #define DD_DEBUGf_TRACE 2
23
24 #define DD_DEBUG_UPDATED_LINESTR (dd_debug & DD_DEBUGf_UPDATED_LINESTR)
25 #define DD_DEBUG_TRACE (dd_debug & DD_DEBUGf_TRACE)
26 static int dd_debug = 0;
27
28 #define DD_CONST_VIA_RV2CV PERL_VERSION_GE(5,11,2)
29
30 #define DD_GROW_VIA_BLOCKHOOK PERL_VERSION_GE(5,13,3)
31
32 #define LEX_NORMAL    10
33 #define LEX_INTERPNORMAL   9
34
35 /* please try not to have a line longer than this :) */
36
37 #define DD_PREFERRED_LINESTR_SIZE 16384
38
39 /* flag to trigger removal of temporary declaree sub */
40
41 static int in_declare = 0;
42
43 /* in 5.10, PL_parser will be NULL if we aren't parsing, and PL_lex_stuff
44    is a lookup into it - so if anything else we can use to tell, so we
45    need to be a bit more careful if PL_parser exists */
46
47 #define DD_AM_LEXING_CHECK (PL_lex_state == LEX_NORMAL || PL_lex_state == LEX_INTERPNORMAL)
48
49 #if defined(PL_parser) || defined(PERL_5_9_PLUS)
50 #define DD_HAVE_PARSER PL_parser
51 #define DD_HAVE_LEX_STUFF (PL_parser && PL_lex_stuff)
52 #define DD_AM_LEXING (PL_parser && DD_AM_LEXING_CHECK)
53 #else
54 #define DD_HAVE_PARSER 1
55 #define DD_HAVE_LEX_STUFF PL_lex_stuff
56 #define DD_AM_LEXING DD_AM_LEXING_CHECK
57 #endif
58
59 /* thing that decides whether we're dealing with a declarator */
60
61 int dd_is_declarator(pTHX_ char* name) {
62   HV* is_declarator;
63   SV** is_declarator_pack_ref;
64   HV* is_declarator_pack_hash;
65   SV** is_declarator_flag_ref;
66   int dd_flags;
67   char* curstash_name;
68
69   is_declarator = get_hv("Devel::Declare::declarators", FALSE);
70
71   if (!is_declarator)
72     return -1;
73
74   /* $declarators{$current_package_name} */
75
76   curstash_name = HvNAME(PL_curstash);
77   if (!curstash_name)
78     return -1;
79
80   is_declarator_pack_ref = hv_fetch(is_declarator, curstash_name,
81                              strlen(curstash_name), FALSE);
82
83   if (!is_declarator_pack_ref || !SvROK(*is_declarator_pack_ref))
84     return -1; /* not a hashref */
85
86   is_declarator_pack_hash = (HV*) SvRV(*is_declarator_pack_ref);
87
88   /* $declarators{$current_package_name}{$name} */
89
90   is_declarator_flag_ref = hv_fetch(
91     is_declarator_pack_hash, name,
92     strlen(name), FALSE
93   );
94
95   /* requires SvIOK as well as TRUE since flags not being an int is useless */
96
97   if (!is_declarator_flag_ref
98         || !SvIOK(*is_declarator_flag_ref)
99         || !SvTRUE(*is_declarator_flag_ref))
100     return -1;
101
102   dd_flags = SvIVX(*is_declarator_flag_ref);
103
104   return dd_flags;
105 }
106
107 /* callback thingy */
108
109 void dd_linestr_callback (pTHX_ char* type, char* name) {
110
111   char* linestr = SvPVX(PL_linestr);
112   int offset = PL_bufptr - linestr;
113
114   dSP;
115
116   ENTER;
117   SAVETMPS;
118
119   PUSHMARK(SP);
120   XPUSHs(sv_2mortal(newSVpv(type, 0)));
121   XPUSHs(sv_2mortal(newSVpv(name, 0)));
122   XPUSHs(sv_2mortal(newSViv(offset)));
123   PUTBACK;
124
125   call_pv("Devel::Declare::linestr_callback", G_VOID|G_DISCARD);
126
127   FREETMPS;
128   LEAVE;
129 }
130
131 char* dd_get_linestr(pTHX) {
132   if (!DD_HAVE_PARSER) {
133     return NULL;
134   }
135   return SvPVX(PL_linestr);
136 }
137
138 void dd_set_linestr(pTHX_ char* new_value) {
139   unsigned int new_len = strlen(new_value);
140
141   if (SvLEN(PL_linestr) < new_len) {
142     croak("PL_linestr not long enough, was Devel::Declare loaded soon enough in %s",
143       CopFILE(&PL_compiling)
144     );
145   }
146
147
148   memcpy(SvPVX(PL_linestr), new_value, new_len+1);
149
150   SvCUR_set(PL_linestr, new_len);
151
152   PL_bufend = SvPVX(PL_linestr) + new_len;
153
154   if ( DD_DEBUG_UPDATED_LINESTR && PERLDB_LINE && PL_curstash != PL_debstash) {
155     /* Cribbed from toke.c */
156     AV *fileav = CopFILEAV(&PL_compiling);
157     if (fileav) {
158       SV * const sv = NEWSV(85,0);
159
160       sv_upgrade(sv, SVt_PVMG);
161       sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
162       (void)SvIOK_on(sv);
163       SvIV_set(sv, 0);
164       av_store(fileav,(I32)CopLINE(&PL_compiling),sv);
165     }
166   }
167 }
168
169 char* dd_get_lex_stuff(pTHX) {
170   return (DD_HAVE_LEX_STUFF ? SvPVX(PL_lex_stuff) : "");
171 }
172
173 void dd_clear_lex_stuff(pTHX) {
174   if (DD_HAVE_PARSER)
175     PL_lex_stuff = (SV*)NULL;
176 }
177
178 char* dd_get_curstash_name(pTHX) {
179   return HvNAME(PL_curstash);
180 }
181
182 int dd_get_linestr_offset(pTHX) {
183   char* linestr;
184   if (!DD_HAVE_PARSER) {
185     return -1;
186   }
187   linestr = SvPVX(PL_linestr);
188   return PL_bufptr - linestr;
189 }
190
191 char* dd_move_past_token (pTHX_ char* s) {
192
193   /*
194    *   buffer will be at the beginning of the declarator, -unless- the
195    *   declarator is at EOL in which case it'll be the next useful line
196    *   so we don't short-circuit out if we don't find the declarator
197    */
198
199   while (s < PL_bufend && isSPACE(*s)) s++;
200   if (memEQ(s, PL_tokenbuf, strlen(PL_tokenbuf)))
201     s += strlen(PL_tokenbuf);
202   return s;
203 }
204
205 int dd_toke_move_past_token (pTHX_ int offset) {
206   char* base_s = SvPVX(PL_linestr) + offset;
207   char* s = dd_move_past_token(aTHX_ base_s);
208   return s - base_s;
209 }
210
211 int dd_toke_scan_word(pTHX_ int offset, int handle_package) {
212   char tmpbuf[sizeof PL_tokenbuf];
213   char* base_s = SvPVX(PL_linestr) + offset;
214   STRLEN len;
215   char* s = scan_word(base_s, tmpbuf, sizeof tmpbuf, handle_package, &len);
216   return s - base_s;
217 }
218
219 int dd_toke_scan_ident(pTHX_ int offset) {
220     char tmpbuf[sizeof PL_tokenbuf];
221     char* base_s = SvPVX(PL_linestr) + offset;
222     char* s = scan_ident(base_s, PL_bufend, tmpbuf, sizeof tmpbuf, 0);
223     return s - base_s;
224 }
225
226 int dd_toke_scan_str(pTHX_ int offset) {
227   char* old_pvx = SvPVX(PL_linestr);
228   SV* line_copy = sv_2mortal(newSVsv(PL_linestr));
229   char* base_s = SvPVX(PL_linestr) + offset;
230   char* s = scan_str(base_s, FALSE, FALSE);
231   if(SvPVX(PL_linestr) != old_pvx)
232     croak("PL_linestr reallocated during scan_str, "
233       "Devel::Declare can't continue");
234   if (!s)
235     return 0;
236   if (s <= base_s || memcmp(SvPVX(line_copy), SvPVX(PL_linestr), offset)) {
237     s += SvCUR(line_copy);
238     sv_catsv(line_copy, PL_linestr);
239     dd_set_linestr(aTHX_ SvPV_nolen(line_copy));
240   }
241   return s - base_s;
242 }
243
244 int dd_toke_skipspace(pTHX_ int offset) {
245   char* old_pvx = SvPVX(PL_linestr);
246   char* base_s = SvPVX(PL_linestr) + offset;
247   char* s = skipspace_force(base_s);
248   if(SvPVX(PL_linestr) != old_pvx)
249     croak("PL_linestr reallocated during skipspace, "
250       "Devel::Declare can't continue");
251   return s - base_s;
252 }
253
254 static void call_done_declare(pTHX) {
255   dSP;
256
257   if (DD_DEBUG_TRACE) {
258     printf("Deconstructing declare\n");
259     printf("PL_bufptr: %s\n", PL_bufptr);
260     printf("bufend at: %i\n", (int)(PL_bufend - PL_bufptr));
261     printf("linestr: %s\n", SvPVX(PL_linestr));
262     printf("linestr len: %i\n", (int)(PL_bufend - SvPVX(PL_linestr)));
263   }
264
265   ENTER;
266   SAVETMPS;
267
268   PUSHMARK(SP);
269
270   call_pv("Devel::Declare::done_declare", G_VOID|G_DISCARD);
271
272   FREETMPS;
273   LEAVE;
274
275   if (DD_DEBUG_TRACE) {
276     printf("PL_bufptr: %s\n", PL_bufptr);
277     printf("bufend at: %i\n", (int)(PL_bufend - PL_bufptr));
278     printf("linestr: %s\n", SvPVX(PL_linestr));
279     printf("linestr len: %i\n", (int)(PL_bufend - SvPVX(PL_linestr)));
280     printf("actual len: %i\n", (int)strlen(PL_bufptr));
281   }
282 }
283
284 static int dd_handle_const(pTHX_ char *name);
285
286 #ifdef CV_NAME_NOTQUAL /* 5.21.5 */
287 # define Gv_or_CvNAME(g) (isGV(g) \
288                ? GvNAME(g) \
289                : SvPV_nolen(cv_name((CV *)SvRV(g), NULL, CV_NAME_NOTQUAL)))
290 #elif defined(CvNAMED) /* 5.21.4 */
291 # define Gv_or_CvNAME(g) (isGV(g) \
292                             ? GvNAME(g) \
293                             : CvNAMED(SvRV(g)) \
294                                 ? HEK_KEY(CvNAME_HEK((CV *)SvRV(g))) \
295                                 : GvNAME(CvGV(SvRV(g))))
296 #else
297 # define Gv_or_CvNAME(g) GvNAME(g)
298 #endif
299
300 /* replacement PL_check rv2cv entry */
301
302 STATIC OP *dd_ck_rv2cv(pTHX_ OP *o, void *user_data) {
303   OP* kid;
304   int dd_flags;
305   char *gvname;
306
307   PERL_UNUSED_VAR(user_data);
308
309   if (!DD_AM_LEXING)
310     return o; /* not lexing? */
311
312   if (in_declare) {
313     call_done_declare(aTHX);
314     return o;
315   }
316
317   kid = cUNOPo->op_first;
318
319   if (kid->op_type != OP_GV) /* not a GV so ignore */
320     return o;
321
322   if (!isGV(kGVOP_gv)
323    && (!SvROK(kGVOP_gv) || SvTYPE(SvRV(kGVOP_gv)) != SVt_PVCV))
324     return o;
325
326   gvname = Gv_or_CvNAME(kGVOP_gv);
327
328   if (DD_DEBUG_TRACE) {
329     printf("Checking GV %s -> %s\n", HvNAME(GvSTASH(kGVOP_gv)), gvname);
330   }
331
332   dd_flags = dd_is_declarator(aTHX_ gvname);
333
334   if (dd_flags == -1)
335     return o;
336
337   if (DD_DEBUG_TRACE) {
338     printf("dd_flags are: %i\n", dd_flags);
339     printf("PL_tokenbuf: %s\n", PL_tokenbuf);
340   }
341
342 #if DD_CONST_VIA_RV2CV
343   if (PL_expect != XOPERATOR) {
344     if (!dd_handle_const(aTHX_ Gv_or_CvNAME(kGVOP_gv)))
345       return o;
346     CopLINE(PL_curcop) = PL_copline;
347     /* The parser behaviour that we're simulating depends on what comes
348        after the declarator. */
349     if (*skipspace(PL_bufptr + strlen(gvname)) != '(') {
350       if (in_declare) {
351         call_done_declare(aTHX);
352       } else {
353         dd_linestr_callback(aTHX_ "rv2cv", gvname);
354       }
355     }
356     return o;
357   }
358 #endif /* DD_CONST_VIA_RV2CV */
359
360   dd_linestr_callback(aTHX_ "rv2cv", gvname);
361
362   return o;
363 }
364
365 #if DD_GROW_VIA_BLOCKHOOK
366
367 static void dd_block_start(pTHX_ int full)
368 {
369   PERL_UNUSED_VAR(full);
370   if (SvLEN(PL_linestr) < DD_PREFERRED_LINESTR_SIZE)
371     (void) lex_grow_linestr(DD_PREFERRED_LINESTR_SIZE);
372 }
373
374 #else /* !DD_GROW_VIA_BLOCKHOOK */
375
376 OP* dd_pp_entereval(pTHX) {
377   dSP;
378   STRLEN len;
379   const char* s;
380   SV *sv;
381 #ifdef PERL_5_9_PLUS
382   SV *saved_hh = NULL;
383   if (PL_op->op_private & OPpEVAL_HAS_HH) {
384     saved_hh = POPs;
385   }
386 #endif
387   sv = POPs;
388   if (SvPOK(sv)) {
389     if (DD_DEBUG_TRACE) {
390       printf("mangling eval sv\n");
391     }
392     if (SvREADONLY(sv))
393       sv = sv_2mortal(newSVsv(sv));
394     s = SvPVX(sv);
395     len = SvCUR(sv);
396     if (!len || s[len-1] != ';') {
397       if (!(SvFLAGS(sv) & SVs_TEMP))
398         sv = sv_2mortal(newSVsv(sv));
399       sv_catpvn(sv, "\n;", 2);
400     }
401     SvGROW(sv, DD_PREFERRED_LINESTR_SIZE);
402   }
403   PUSHs(sv);
404 #ifdef PERL_5_9_PLUS
405   if (PL_op->op_private & OPpEVAL_HAS_HH) {
406     PUSHs(saved_hh);
407   }
408 #endif
409   return PL_ppaddr[OP_ENTEREVAL](aTHX);
410 }
411
412 STATIC OP *dd_ck_entereval(pTHX_ OP *o, void *user_data) {
413   PERL_UNUSED_VAR(user_data);
414
415   if (o->op_ppaddr == PL_ppaddr[OP_ENTEREVAL])
416     o->op_ppaddr = dd_pp_entereval;
417   return o;
418 }
419
420 #endif /* !DD_GROW_VIA_BLOCKHOOK */
421
422 static I32 dd_filter_realloc(pTHX_ int idx, SV *sv, int maxlen)
423 {
424   SV *filter_datasv;
425   const I32 count = FILTER_READ(idx+1, sv, maxlen);
426   SvGROW(sv, DD_PREFERRED_LINESTR_SIZE);
427   /* Filters can only be deleted in the correct order (reverse of the
428      order in which they were added).  Insisting on deleting the filter
429      here would break if another filter were added after ours and is
430      still around.  Not deleting the filter at all would break if another
431      filter were added earlier and attempts to delete itself later.
432      We can play nicely to the maximum possible extent by deleting our
433      filter iff it is currently deletable (i.e., it is on the top of
434      the filter stack).  Can still run into trouble in more complex
435      situations, but can't avoid that. */
436   if (PL_rsfp_filters && AvFILLp(PL_rsfp_filters) >= 0 &&
437       (filter_datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters))) &&
438       IoANY(filter_datasv) == FPTR2DPTR(void *, dd_filter_realloc)) {
439     filter_del(dd_filter_realloc);
440   }
441   return count;
442 }
443
444 static int dd_handle_const(pTHX_ char *name) {
445   switch (PL_lex_inwhat) {
446     case OP_QR:
447     case OP_MATCH:
448     case OP_SUBST:
449     case OP_TRANS:
450     case OP_BACKTICK:
451     case OP_STRINGIFY:
452       return 0;
453       break;
454     default:
455       break;
456   }
457
458   if (strnEQ(PL_bufptr, "->", 2)) {
459     return 0;
460   }
461
462   {
463     char buf[256];
464     STRLEN len;
465     char *s = PL_bufptr;
466     STRLEN old_offset = PL_bufptr - SvPVX(PL_linestr);
467
468     s = scan_word(s, buf, sizeof buf, FALSE, &len);
469     if (strnEQ(buf, name, len)) {
470       char *d;
471       SV *inject = newSVpvn(SvPVX(PL_linestr), PL_bufptr - SvPVX(PL_linestr));
472       sv_catpvn(inject, buf, len);
473
474       d = peekspace(s);
475       sv_catpvn(inject, s, d - s);
476
477       if ((PL_bufend - d) >= 2 && strnEQ(d, "=>", 2)) {
478         return 0;
479       }
480
481       sv_catpv(inject, d);
482       dd_set_linestr(aTHX_ SvPV_nolen(inject));
483       PL_bufptr = SvPVX(PL_linestr) + old_offset;
484       SvREFCNT_dec (inject);
485     }
486   }
487
488   dd_linestr_callback(aTHX_ "const", name);
489
490   return 1;
491 }
492
493 #if !DD_CONST_VIA_RV2CV
494
495 STATIC OP *dd_ck_const(pTHX_ OP *o, void *user_data) {
496   int dd_flags;
497   char* name;
498
499   PERL_UNUSED_VAR(user_data);
500
501   if (DD_HAVE_PARSER && PL_expect == XOPERATOR) {
502     return o;
503   }
504
505   /* if this is set, we just grabbed a delimited string or something,
506      not a bareword, so NO TOUCHY */
507
508   if (DD_HAVE_LEX_STUFF)
509     return o;
510
511   /* don't try and look this up if it's not a string const */
512   if (!SvPOK(cSVOPo->op_sv))
513     return o;
514
515   name = SvPVX(cSVOPo->op_sv);
516
517   dd_flags = dd_is_declarator(aTHX_ name);
518
519   if (dd_flags == -1)
520     return o;
521
522   dd_handle_const(aTHX_ name);
523
524   return o;
525 }
526
527 #endif /* !DD_CONST_VIA_RV2CV */
528
529 STATIC void dd_initialize(pTHX) {
530   static int initialized = 0;
531   if (!initialized) {
532     initialized = 1;
533 #if DD_GROW_VIA_BLOCKHOOK
534     {
535       static BHK bhk;
536 #if PERL_VERSION_GE(5,13,6)
537       BhkENTRY_set(&bhk, bhk_start, dd_block_start);
538 #else /* <5.13.6 */
539       BhkENTRY_set(&bhk, start, dd_block_start);
540 #endif /* <5.13.6 */
541       Perl_blockhook_register(aTHX_ &bhk);
542     }
543 #else /* !DD_GROW_VIA_BLOCKHOOK */
544     hook_op_check(OP_ENTEREVAL, dd_ck_entereval, NULL);
545 #endif /* !DD_GROW_VIA_BLOCKHOOK */
546     hook_op_check(OP_RV2CV, dd_ck_rv2cv, NULL);
547 #if !DD_CONST_VIA_RV2CV
548     hook_op_check(OP_CONST, dd_ck_const, NULL);
549 #endif /* !DD_CONST_VIA_RV2CV */
550   }
551 }
552
553 MODULE = Devel::Declare  PACKAGE = Devel::Declare
554
555 PROTOTYPES: DISABLE
556
557 void
558 initialize()
559   CODE:
560     dd_initialize(aTHX);
561
562 void
563 setup()
564   CODE:
565     dd_initialize(aTHX);
566     filter_add(dd_filter_realloc, NULL);
567
568 char*
569 get_linestr()
570   CODE:
571     RETVAL = dd_get_linestr(aTHX);
572   OUTPUT:
573     RETVAL
574
575 void
576 set_linestr(char* new_value)
577   CODE:
578     dd_set_linestr(aTHX_ new_value);
579
580 char*
581 get_lex_stuff()
582   CODE:
583     RETVAL = dd_get_lex_stuff(aTHX);
584   OUTPUT:
585     RETVAL
586
587 void
588 clear_lex_stuff()
589   CODE:
590     dd_clear_lex_stuff(aTHX);
591
592 char*
593 get_curstash_name()
594   CODE:
595     RETVAL = dd_get_curstash_name(aTHX);
596   OUTPUT:
597     RETVAL
598
599 int
600 get_linestr_offset()
601   CODE:
602     RETVAL = dd_get_linestr_offset(aTHX);
603   OUTPUT:
604     RETVAL
605
606 int
607 toke_scan_word(int offset, int handle_package)
608   CODE:
609     RETVAL = dd_toke_scan_word(aTHX_ offset, handle_package);
610   OUTPUT:
611     RETVAL
612
613 int
614 toke_move_past_token(int offset);
615   CODE:
616     RETVAL = dd_toke_move_past_token(aTHX_ offset);
617   OUTPUT:
618     RETVAL
619
620 SV*
621 toke_scan_str(int offset);
622   PREINIT:
623     int len;
624   CODE:
625     len = dd_toke_scan_str(aTHX_ offset);
626     RETVAL = len ? newSViv(len) : &PL_sv_undef;
627   OUTPUT:
628     RETVAL
629
630 int
631 toke_scan_ident(int offset)
632   CODE:
633     RETVAL = dd_toke_scan_ident(aTHX_ offset);
634   OUTPUT:
635     RETVAL
636
637 int
638 toke_skipspace(int offset)
639   CODE:
640     RETVAL = dd_toke_skipspace(aTHX_ offset);
641   OUTPUT:
642     RETVAL
643
644 int
645 get_in_declare()
646   CODE:
647     RETVAL = in_declare;
648   OUTPUT:
649     RETVAL
650
651 void
652 set_in_declare(int value)
653   CODE:
654     in_declare = value;
655
656 BOOT:
657 {
658   char *endptr;
659   char *debug_str = getenv ("DD_DEBUG");
660   if (debug_str) {
661     dd_debug = strtol (debug_str, &endptr, 10);
662     if (*endptr != '\0') {
663       dd_debug = 0;
664     }
665   }
666 }