C.xs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. #define PERL_NO_GET_CONTEXT
  2. #include <EXTERN.h>
  3. #include <perl.h>
  4. #include <XSUB.h>
  5. #ifndef PM_GETRE
  6. # if defined(USE_ITHREADS) && (PERL_VERSION > 8)
  7. # define PM_GETRE(o) (INT2PTR(REGEXP*,SvIVX(PL_regex_pad[(o)->op_pmoffset])))
  8. # else
  9. # define PM_GETRE(o) ((o)->op_pmregexp)
  10. # endif
  11. #endif
  12. /* hack for 5.6.2: just want to know if PMf_ONCE or 0 */
  13. #ifndef PmopSTASHPV
  14. # define PmopSTASHPV(o) ((o)->op_pmflags & PMf_ONCE)
  15. #endif
  16. #ifndef RX_EXTFLAGS
  17. # define RX_EXTFLAGS(prog) ((prog)->extflags)
  18. #endif
  19. #if PERL_VERSION > 17 && (PERL_VERSION < 19 || (PERL_VERSION == 19 && PERL_SUBVERSION < 4))
  20. #define need_op_slabbed
  21. #endif
  22. #if PERL_VERSION == 19 && (PERL_SUBVERSION > 2 && PERL_SUBVERSION <= 4)
  23. #define need_op_folded
  24. #endif
  25. typedef struct magic *B__MAGIC;
  26. #if PERL_VERSION > 17
  27. typedef PADNAME *B__PADNAME;
  28. #endif
  29. #if PERL_VERSION > 21
  30. typedef PADLIST *B__PADLIST;
  31. typedef PADNAMELIST *B__PADNAMELIST;
  32. #endif
  33. #if PERL_VERSION >= 11
  34. typedef struct p5rx *B__REGEXP;
  35. #endif
  36. typedef COP *B__COP;
  37. typedef OP *B__OP;
  38. typedef HV *B__HV;
  39. STATIC U32 a_hash = 0;
  40. typedef struct {
  41. U32 bits;
  42. IV require_tag;
  43. } a_hint_t;
  44. #if PERL_VERSION >= 10
  45. static const char* const svclassnames[] = {
  46. "B::NULL",
  47. #if PERL_VERSION < 19
  48. "B::BIND",
  49. #endif
  50. "B::IV",
  51. "B::NV",
  52. #if PERL_VERSION <= 10
  53. "B::RV",
  54. #endif
  55. "B::PV",
  56. #if PERL_VERSION >= 19
  57. "B::INVLIST",
  58. #endif
  59. "B::PVIV",
  60. "B::PVNV",
  61. "B::PVMG",
  62. #if PERL_VERSION >= 11
  63. "B::REGEXP",
  64. #endif
  65. "B::GV",
  66. "B::PVLV",
  67. "B::AV",
  68. "B::HV",
  69. "B::CV",
  70. "B::FM",
  71. "B::IO",
  72. };
  73. #define MY_CXT_KEY "B::C::_guts" XS_VERSION
  74. typedef struct {
  75. int x_walkoptree_debug; /* Flag for walkoptree debug hook */
  76. SV * x_specialsv_list[7];
  77. } my_cxt_t;
  78. START_MY_CXT
  79. #define walkoptree_debug (MY_CXT.x_walkoptree_debug)
  80. #define specialsv_list (MY_CXT.x_specialsv_list)
  81. static SV *
  82. make_sv_object(pTHX_ SV *sv)
  83. {
  84. SV *const arg = sv_newmortal();
  85. const char *type = 0;
  86. IV iv;
  87. dMY_CXT;
  88. for (iv = 0; iv < (IV)(sizeof(specialsv_list)/sizeof(SV*)); iv++) {
  89. if (sv == specialsv_list[iv]) {
  90. type = "B::SPECIAL";
  91. break;
  92. }
  93. }
  94. if (!type) {
  95. type = svclassnames[SvTYPE(sv)];
  96. iv = PTR2IV(sv);
  97. }
  98. sv_setiv(newSVrv(arg, type), iv);
  99. return arg;
  100. }
  101. #endif
  102. static int
  103. my_runops(pTHX)
  104. {
  105. HV* regexp_hv = get_hv( "B::C::Regexp", GV_ADD );
  106. SV* key = newSViv( 0 );
  107. DEBUG_l(Perl_deb(aTHX_ "Entering new RUNOPS level (B::C)\n"));
  108. do {
  109. #if (PERL_VERSION < 13) || ((PERL_VERSION == 13) && (PERL_SUBVERSION < 2))
  110. PERL_ASYNC_CHECK();
  111. #endif
  112. if (PL_debug) {
  113. if (PL_watchaddr && (*PL_watchaddr != PL_watchok))
  114. PerlIO_printf(Perl_debug_log,
  115. "WARNING: %"UVxf" changed from %"UVxf" to %"UVxf"\n",
  116. PTR2UV(PL_watchaddr), PTR2UV(PL_watchok),
  117. PTR2UV(*PL_watchaddr));
  118. #if defined(DEBUGGING) \
  119. && !(defined(_WIN32) || (defined(__CYGWIN__) && (__GNUC__ > 3)) || defined(AIX))
  120. # if (PERL_VERSION > 7)
  121. if (DEBUG_s_TEST_) debstack();
  122. if (DEBUG_t_TEST_) debop(PL_op);
  123. # else
  124. DEBUG_s(debstack());
  125. DEBUG_t(debop(PL_op));
  126. # endif
  127. #endif
  128. }
  129. /* Need to store the rx all for QR PMOPs in a global %Regexp hash. MATCH once also */
  130. #if 1
  131. if ((PL_op->op_type == OP_QR)
  132. || ((PL_op->op_type == OP_MATCH) && PmopSTASHPV((PMOP*)PL_op)))
  133. #else
  134. if ((PL_op->op_type == OP_QR)
  135. || (PL_op->op_type == OP_MATCH)
  136. || (PL_op->op_type == OP_PUSHRE)
  137. || (PL_op->op_type == OP_SUBST))
  138. #endif
  139. {
  140. PMOP* op;
  141. REGEXP* rx = PM_GETRE( (PMOP*)PL_op );
  142. SV* rv = newSViv( 0 );
  143. New(0, op, 1, PMOP );
  144. Copy( PL_op, op, 1, PMOP );
  145. /* we need just the flags */
  146. op->op_next = NULL;
  147. op->op_sibling = NULL;
  148. op->op_first = NULL;
  149. op->op_last = NULL;
  150. #if PERL_VERSION < 10
  151. op->op_pmreplroot = NULL;
  152. op->op_pmreplstart = NULL;
  153. op->op_pmnext = NULL;
  154. #endif
  155. #if defined(USE_ITHREADS) && (PERL_VERSION > 7)
  156. op->op_pmoffset = 0;
  157. #else
  158. op->op_pmregexp = 0;
  159. #endif
  160. sv_setiv( key, PTR2IV( rx ) );
  161. sv_setref_iv( rv, "B::PMOP", PTR2IV( op ) );
  162. #if defined(DEBUGGING) && (PERL_VERSION > 7)
  163. if (DEBUG_D_TEST_) fprintf(stderr, "pmop %p => rx %p\n", op, rx);
  164. #endif
  165. hv_store_ent( regexp_hv, key, rv, 0 );
  166. }
  167. } while ((PL_op = CALL_FPTR(PL_op->op_ppaddr)(aTHX)));
  168. SvREFCNT_dec( key );
  169. TAINT_NOT;
  170. return 0;
  171. }
  172. MODULE = B__MAGIC PACKAGE = B::MAGIC
  173. #if PERL_VERSION < 7
  174. SV*
  175. precomp(mg)
  176. B::MAGIC mg
  177. CODE:
  178. if (mg->mg_type == 'r') {
  179. REGEXP* rx = (REGEXP*)mg->mg_obj;
  180. RETVAL = Nullsv;
  181. if (rx)
  182. RETVAL = newSVpvn( rx->precomp, rx->prelen );
  183. }
  184. else {
  185. croak( "precomp is only meaningful on r-magic" );
  186. }
  187. OUTPUT:
  188. RETVAL
  189. #endif
  190. MODULE = B PACKAGE = B::PMOP
  191. #if defined(RX_UTF8) && PERL_VERSION < 20
  192. SV*
  193. precomp(o)
  194. B::OP o
  195. PPCODE:
  196. {
  197. if (SvROK(ST(0))) {
  198. IV tmp = SvIV((SV*)SvRV(ST(0)));
  199. o = INT2PTR(B__OP,tmp);
  200. }
  201. else
  202. croak("precomp(o) argument is not a reference");
  203. if (o) {
  204. REGEXP *rx = PM_GETRE(cPMOPo);
  205. if (!rx)
  206. XSRETURN_UNDEF;
  207. ST(0) = sv_2mortal(newSVpvn_flags(RX_PRECOMP(rx), RX_PRELEN(rx), RX_UTF8(rx) ? SVf_UTF8 : 0));
  208. XSRETURN(1);
  209. } else {
  210. XSRETURN_UNDEF;
  211. }
  212. }
  213. #endif
  214. MODULE = B PACKAGE = B::HV
  215. #if PERL_VERSION > 17
  216. SV*
  217. SvSTASH(hv)
  218. B::HV hv
  219. PPCODE:
  220. HV* stash = SvSTASH(MUTABLE_SV(hv)); /* [perl #126410] */
  221. ST(0) = (char*)stash < (char*)PL_sv_arenaroot
  222. ? &PL_sv_undef : make_sv_object(aTHX_ MUTABLE_SV(stash));
  223. XSRETURN(1);
  224. #endif
  225. MODULE = B PACKAGE = B::UNOP_AUX
  226. #if PERL_VERSION > 21
  227. SV*
  228. aux(o)
  229. B::OP o
  230. CODE:
  231. UNOP_AUX_item *items = cUNOP_AUXo->op_aux;
  232. UV len = items[-1].uv;
  233. RETVAL = newSVpvn_flags((char*)&items[-1], (1+len) * sizeof(UNOP_AUX_item), 0);
  234. OUTPUT:
  235. RETVAL
  236. #endif
  237. #if PERL_VERSION > 21
  238. MODULE = B PACKAGE = B::PADNAME PREFIX = Padname
  239. int
  240. PadnameGEN(padn)
  241. B::PADNAME padn
  242. CODE:
  243. RETVAL = padn->xpadn_gen;
  244. OUTPUT:
  245. RETVAL
  246. MODULE = B PACKAGE = B::PADLIST PREFIX = Padlist
  247. U32
  248. PadlistID(padlist)
  249. B::PADLIST padlist
  250. ALIAS: B::PADLIST::OUTID = 1
  251. CODE:
  252. RETVAL = ix ? padlist->xpadl_outid : padlist->xpadl_id;
  253. OUTPUT:
  254. RETVAL
  255. MODULE = B PACKAGE = B::PADNAMELIST PREFIX = Padnamelist
  256. size_t
  257. PadnamelistMAXNAMED(padnl)
  258. B::PADNAMELIST padnl
  259. #endif
  260. MODULE = B PACKAGE = B::REGEXP PREFIX = RX_
  261. #if PERL_VERSION > 10
  262. U32
  263. RX_EXTFLAGS(rx)
  264. B::REGEXP rx
  265. #endif
  266. MODULE = B PACKAGE = B::COP PREFIX = COP_
  267. #if (PERL_VERSION >= 15) && defined(USE_ITHREADS) && defined(CopSTASH_flags)
  268. #define COP_stashflags(o) CopSTASH_flags(o)
  269. U32
  270. COP_stashflags(o)
  271. B::COP o
  272. #endif
  273. #ifdef CopLABEL_len_flags
  274. SV*
  275. COP_label(o)
  276. B::OP o
  277. PPCODE:
  278. {
  279. STRLEN len;
  280. U32 flags;
  281. const char *pv = CopLABEL_len_flags(cCOPo, &len, &flags);
  282. ST(0) = pv ? sv_2mortal(newSVpvn_flags(pv, len, flags))
  283. : &PL_sv_undef;
  284. }
  285. XSRETURN(1);
  286. #endif
  287. MODULE = B__CC PACKAGE = B::CC
  288. PROTOTYPES: DISABLE
  289. # Perl_ck_null is not exported on Windows, so disable autovivification optimizations there
  290. U32
  291. _autovivification(cop)
  292. B::COP cop
  293. CODE:
  294. {
  295. SV *hint;
  296. IV h;
  297. RETVAL = 1;
  298. if (PL_check[OP_PADSV] != PL_check[0]) {
  299. char *package = CopSTASHPV(cop);
  300. #ifdef cop_hints_fetch_pvn
  301. hint = cop_hints_fetch_pvn(cop, "autovivification", strlen("autovivification"), a_hash, 0);
  302. #elif PERL_VERSION > 9
  303. hint = Perl_refcounted_he_fetch(aTHX_ cop->cop_hints_hash,
  304. NULL, "autovivification", strlen("autovivification"), 0, a_hash);
  305. #else
  306. SV **val = hv_fetch(GvHV(PL_hintgv), "autovivification", strlen("autovivification"), 0);
  307. if (!val)
  308. return;
  309. hint = *val;
  310. #endif
  311. if (!(hint && SvIOK(hint)))
  312. return;
  313. h = SvIVX(hint);
  314. if (h & 4) /* A_HINT_FETCH 4 */
  315. RETVAL = 0;
  316. }
  317. }
  318. OUTPUT:
  319. RETVAL
  320. MODULE = B__OP PACKAGE = B::OP PREFIX = op_
  321. #ifdef need_op_slabbed
  322. I32
  323. op_slabbed(op)
  324. B::OP op
  325. PPCODE:
  326. PUSHi(op->op_slabbed);
  327. I32
  328. op_savefree(op)
  329. B::OP op
  330. PPCODE:
  331. PUSHi(op->op_savefree);
  332. I32
  333. op_static(op)
  334. B::OP op
  335. PPCODE:
  336. PUSHi(op->op_static);
  337. #endif
  338. #ifdef need_op_folded
  339. I32
  340. op_folded(op)
  341. B::OP op
  342. PPCODE:
  343. PUSHi(op->op_folded);
  344. #endif
  345. MODULE = B PACKAGE = B::HV PREFIX = Hv
  346. #if PERL_VERSION >= 10
  347. void
  348. HvARRAY_utf8(hv)
  349. B::HV hv
  350. PPCODE:
  351. if (HvKEYS(hv) > 0) {
  352. HE *he;
  353. (void)hv_iterinit(hv);
  354. EXTEND(sp, HvKEYS(hv) * 2);
  355. while ((he = hv_iternext(hv))) {
  356. if (HeSVKEY(he)) {
  357. mPUSHs(HeSVKEY(he));
  358. } else if (HeKUTF8(he)) {
  359. PUSHs(newSVpvn_flags(HeKEY(he), HeKLEN(he), SVf_UTF8|SVs_TEMP));
  360. } else {
  361. PUSHs(newSVpvn_flags(HeKEY(he), HeKLEN(he), SVs_TEMP));
  362. }
  363. PUSHs(make_sv_object(aTHX_ HeVAL(he)));
  364. }
  365. }
  366. #endif
  367. MODULE = B__C PACKAGE = B::C
  368. PROTOTYPES: DISABLE
  369. #if PERL_VERSION >= 11
  370. CV*
  371. method_cv(meth, packname)
  372. SV* meth;
  373. char *packname;
  374. CODE:
  375. U32 hash;
  376. HV* stash; /* XXX from op before, also on the run-time stack */
  377. GV* gv;
  378. hash = SvSHARED_HASH(meth);
  379. stash = gv_stashpv(packname, TRUE);
  380. if (hash) {
  381. const HE* const he = hv_fetch_ent(stash, meth, 0, hash);
  382. if (he) {
  383. gv = MUTABLE_GV(HeVAL(he));
  384. if (isGV(gv) && GvCV(gv) &&
  385. (!GvCVGEN(gv) || GvCVGEN(gv)
  386. == (PL_sub_generation + HvMROMETA(stash)->cache_gen)))
  387. RETVAL = (CV*)MUTABLE_SV(GvCV(gv));
  388. return;
  389. }
  390. }
  391. /* public API since 5.11 */
  392. gv = gv_fetchmethod_flags(stash,
  393. SvPV_nolen_const(meth),
  394. GV_AUTOLOAD | GV_CROAK);
  395. assert(gv);
  396. RETVAL = isGV(gv) ? (CV*)MUTABLE_SV(GvCV(gv)) : (CV*)MUTABLE_SV(gv);
  397. OUTPUT:
  398. RETVAL
  399. #endif
  400. BOOT:
  401. #if PERL_VERSION >= 10
  402. {
  403. MY_CXT_INIT;
  404. #endif
  405. PL_runops = my_runops;
  406. #if PERL_VERSION >= 10
  407. {
  408. dMY_CXT;
  409. specialsv_list[0] = Nullsv;
  410. specialsv_list[1] = &PL_sv_undef;
  411. specialsv_list[2] = &PL_sv_yes;
  412. specialsv_list[3] = &PL_sv_no;
  413. specialsv_list[4] = (SV *) pWARN_ALL;
  414. specialsv_list[5] = (SV *) pWARN_NONE;
  415. specialsv_list[6] = (SV *) pWARN_STD;
  416. }
  417. }
  418. #endif