/* * I have no idea where this file came from * * Copyright (C) 1999, Ashley Winters * * You may distribute under the terms of the LGPL as specified in the * README.LICENSE file which should be included with this library. * */ #include "pig.h" #include #include #include #include "pigvirtual.h" #include "pigtype_object.h" #include "pigfunc_object.h" #include "pigclassinfo.h" #include "pigsigslot.h" #include "pigperl.h" class pig_public_QObject : public QObject { public: void doInitMetaObject() { this->initMetaObject(); } class QMetaObject *doMetaObject() { return this->metaObject(); } }; void break_it_here() { } static bool pig_is_perl_receiver(QMetaObject *pigm, const char *pigproto) { if(pig_classinfo_fetch(pigm->className())) // if(QClass) return false return FALSE; if(pigm->signal(pigproto, FALSE) || pigm->slot(pigproto, FALSE)) return TRUE; else if(pigm->superClass()) return pig_is_perl_receiver(pigm->superClass(), pigproto); return FALSE; } // pig0 = object, pig1 = member PIG_DEFINE_FUNC_2(bool, pig_receiver_defined, SV *, SV *) { PIGARGS; STRLEN n_a; SV *pigprotosv = pig_parse_proto(pig1); const char *pigproto = SvPV(pigprotosv, n_a); //warn("Is there a receiver defined for %s?\n", pigproto); pig_object_data *pigd = pig_object_extract(pig0); QObject *pigobj = (QObject *)pig_object_cast(pigd, "QObject"); QMetaObject *pigm = pigobj->metaObject(); bool pigr = pig_is_perl_receiver(pigm, pigproto); SvREFCNT_dec(pigprotosv); return pigr; } // pig0 = object, pig1 = member PIG_DEFINE_FUNC_2(class QObject *, pig_create_slot, SV *, SV *) { PIGARGS; STRLEN n_a; //printf("WHOOPS!\n"); SV *pigprotosv = pig_parse_proto(pig1); const char *pigproto = SvPV(pigprotosv, n_a); pig_slot_data *pigsd; pig_object_data *pigd = pig_object_extract(pig0); QObject *pigobj = (QObject *)pig_object_cast(pigd, "QObject"); QMetaObject *pigm = pigobj->metaObject(); pigsd = new pig_slot_data; pigsd->pigreceiver = newSVsv(pig0); //printf("%p = %p\n", pigsd->pigreceiver, SvRV(pig0)); //SvREFCNT_dec(SvRV(pig0)); pigsd->pigproto = new char[strlen(pigproto) + 1]; strcpy((char *)pigsd->pigproto, pigproto); pigsd->pigcrypt = SvPV(pig_map_proto(pigprotosv), n_a); pigsd->pigmethod = pigsd->pigcrypt + 2; pigsd->pigmeta = pigm; pig_S *pigslot = new pig_S; pigslot->pigsd = pigsd; //warn("Created slot %p\n", pigslot); // pigslot->connect(pigobj, SIGNAL(destroyed()), SLOT(pig_S_destroyed())); // QObject::connect(pigobj, SIGNAL(destroyed()), pigslot, //SLOT(pig_S_destroyed())); //warn("Connecting %p to %p\n", pigobj, pigslot); return pigslot; } PIG_DEFINE_FUNC_2(const char *, pig_member_string, SV *, SV *) { PIGARGS; STRLEN n_a; //printf("Well... %s %s\n", SvPV(pig0, na), SvPV(pig1, na)); if(!SvOK(pig0) || !SvOK(pig1)) return 0; SV *pigprotosv = pig_parse_proto(pig1); //printf("It wasn't there\n"); const char *pigproto = SvPV(pigprotosv, n_a); pig_object_data *pigd = pig_object_extract(pig0); QObject *pigobj = (QObject *)pig_object_cast(pigd, "QObject"); //printf("Looks like we got a %s\n", pigobj->className()); QMetaObject *pigm = pigobj->metaObject(); SV *pigr = sv_newmortal(); if(pigm->signal(pigproto, TRUE)) sv_setiv(pigr, SIGNAL_CODE); else sv_setiv(pigr, SLOT_CODE); sv_catpv(pigr, (char *)pigproto); //printf("Got the member for %s\n", pigproto); return SvPVX(pigr); } void pig_assign_pigd(pig_object_data *pigd, void *pigptr, pig_classinfo *piginfo, long pigflags) { pigd->pigptr = pigptr; pigd->piginfo = piginfo; pigd->pigflags = pigflags; //printf("okay, %p -> %p:%p:%x\n", pigd, pigd->pigptr, pigd->piginfo, pigd->pigflags); } PIG_DEFINE_FUNC_3(SV *, pig_new_castobject, void *, const char *, const char *) { pig_object_data *pigd; SV *pigr = sv_2mortal(pig_object_create(pig2, &pigd)); pig_assign_pigd(pigd, pig0, pig_classinfo_fetch(pig1), PIGOBJECT_ALLOCATED); pig_virtual *pigv = (pig_virtual *)(*pigd->piginfo->pigtocastfunc)("virtual", pig0); if(pigv) pig_virtual_setobject(pigv, pigr); QObject *pigobj = (QObject *)(*pigd->piginfo->pigtocastfunc)("QObject", pig0); if(pigobj) ((pig_public_QObject *)pigobj)->doInitMetaObject(); return pigr; } PIG_DEFINE_VOID_FUNC_3(pig_type_new_castobject_return, void *, const char *, const char *) { PIGRET; pig_object_data *pigd; SV *pigr = sv_2mortal(pig_object_create(pig2, &pigd)); pig_assign_pigd(pigd, pig0, pig_classinfo_fetch(pig1), PIGOBJECT_ALLOCATED); pig_virtual *pigv = (pig_virtual *)(*pigd->piginfo->pigtocastfunc)("virtual", pig0); if(pigv) pig_virtual_setobject(pigv, pigr); QObject *pigobj = (QObject *)(*pigd->piginfo->pigtocastfunc)("QObject", pig0); if(pigobj) ((pig_public_QObject *)pigobj)->doInitMetaObject(); // sv_bless(PIG_RETARG, gv_stashpv((char *)pig2, TRUE)); PIGRETURN(pigr); } PIG_DEFINE_VOID_FUNC_2(pig_type_new_object_return, void *, const char *) { PIGRET; pig_object_data *pigd; if(!pig0) { PIGRETURN(sv_mortalcopy(&PIGsv_undef)); } SV *pigr = sv_2mortal(pig_object_create(pig_map_class(pig1), &pigd)); //printf("Creating %s(%p)\n", pig_map_class(pig1), pig0); pig_assign_pigd(pigd, pig0, pig_classinfo_fetch(pig1), PIGOBJECT_ALLOCATED); // pig_virtual *pigv = // (pig_virtual *)(*pigd->piginfo->pigtocastfunc)("virtual", pig0); // if(pigv) pig_virtual_setobject(pigv, PIG_RETARG); // sv_bless(pigr, gv_stashpv((char *)pig_map_class(pig1), TRUE)); //printf("Returning %p => %p\n", pigr, SvRV(pigr)); PIGRETURN(pigr); } PIG_DEFINE_FUNC_1(void *, pig_type_object_destructor_argument, const char *) { PIGARGS; //PIGstack_sp - (PIGstack_base + TOPMARK) pig_object_data *pigd = pig_object_extract(PIG_ARG); //printf("Argument %d = %p => %p == %p\n", pig_argument_idx, PIG_ARG, pigd, pigd->pigptr); if(!pigd) return 0; PIGARGUMENT(pig_object_cast(pigd, pig0)); } PIG_DEFINE_VOID_FUNC_2(pig_object_destroy, void *, class pig_virtual *) { } /* borrowed from Perl source under GPL */ static bool pig_isa_lookup(HV *stash, char *name, int len, int level) { AV* av; GV* gv; GV** gvp; HV* hv = Nullhv; if (!stash) return FALSE; if(strEQ(HvNAME(stash), name)) return TRUE; if (level > 100) croak("Recursive inheritance detected in package '%s'", HvNAME(stash)); gvp = (GV**)hv_fetch(stash, (char *)"::ISA::CACHE::", 14, FALSE); if (gvp && (gv = *gvp) != (GV*)&PIGsv_undef && (hv = GvHV(gv))) { SV* sv; SV** svp = (SV**)hv_fetch(hv, name, len, FALSE); if (svp && (sv = *svp) != (SV*)&PIGsv_undef) return SvTRUE(sv); } gvp = (GV**)hv_fetch(stash,(char *)"ISA",3,FALSE); if (gvp && (gv = *gvp) != (GV*)&PIGsv_undef && (av = GvAV(gv))) { if(!hv) { gvp = (GV**)hv_fetch(stash, (char *)"::ISA::CACHE::", 14, TRUE); gv = *gvp; if (SvTYPE(gv) != SVt_PVGV) gv_init(gv, stash, (char *)"::ISA::CACHE::", 14, TRUE); hv = GvHVn(gv); } if(hv) { SV** svp = AvARRAY(av); /* NOTE: No support for tied ISA */ I32 items = AvFILL(av) + 1; while (items--) { SV* sv = *svp++; HV* basestash = gv_stashsv(sv, FALSE); if (!basestash) { if (PIGdowarn) warn("Can't locate package %s for @%s::ISA", SvPVX(sv), HvNAME(stash)); continue; } if(pig_isa_lookup(basestash, name, len, level + 1)) { (void)hv_store(hv,name,len,&PIGsv_yes,0); return TRUE; } } (void)hv_store(hv,name,len,&PIGsv_no,0); } } return strEQ(name, "UNIVERSAL"); } /* end borrowed Perl source */ bool pig_class_isa(HV *pigstash, const char *pigclass) { bool pigr = pig_isa_lookup(pigstash, (char *)pigclass, strlen(pigclass), 0); return pigr; } extern QMember pig_slot_matrix[]; extern int pig_sigslot_exp_table[]; extern int pig_sigslot_typeidx(char); extern void pig_push_slot_arguments(const char *); void pigslot(pig_S *pigthis) { dSP; pig_slot_data *pigsd = pigthis->pigsd; ENTER; SAVETMPS; PUSHMARK(sp); XPUSHs(sv_mortalcopy(pigsd->pigreceiver)); PUTBACK; pig_push_slot_arguments(pigsd->pigcrypt); SPAGAIN; perl_call_method((char *)pigsd->pigmethod, G_DISCARD); SPAGAIN; FREETMPS; LEAVE; } PIG_DEFINE_FUNC_1(int, pig_sigslot_hash, const char *) { int pigr = 0, pigcnt = *pig0; pig_sigslot_argument_iterator pig_argit(pig0); int pigi; for(pigi = 0; pigi < pigcnt; pigi++) pigr += pig_sigslot_exp_table[pigcnt - (pigi+1)] * pig_sigslot_typeidx(*++pig_argit); return pigr; } PIG_DEFINE_FUNC_1(QMember, pig_sigslot_stub, SV *) { STRLEN n_a; int pigidx = pig_sigslot_hash(SvPV(pig0, n_a)); return pig_slot_matrix[pigidx]; } static QMetaData *pig_createMetaData(HV *pighv, bool pigslot, int *pigcount = 0) { int pigcnt = 0; int pigkeys = 0; if(!pighv) { if(pigcount) *pigcount = 0; return 0; } pigkeys = HvKEYS(pighv); QMetaData *pigtbl = new QMetaData[pigslot ? pigkeys + 1 : pigkeys]; char *pigkey; I32 piglen; SV *pigvalue; hv_iterinit(pighv); for(pigcnt = 0; pigcnt < pigkeys; pigcnt++) { pigvalue = hv_iternextsv(pighv, &pigkey, &piglen); pigtbl[pigcnt].name = pigkey; pigtbl[pigcnt].ptr = pig_sigslot_stub(pigvalue); } if(pigslot) { pigtbl[pigcnt].name = (char *)"pig_S_destroyed()"; pigtbl[pigcnt].ptr = (QMember)&pig_S::pig_S_destroyed; pigcnt++; } if(pigcount) *pigcount = pigcnt; return pigtbl; } PIG_DEFINE_FUNC_2(class QMetaObject *, pig_createMetaObject, const char *, class QMetaObject *) { int pigsigcnt, pigslotcnt; QMetaData *pigsigmeta, *pigslotmeta; HV *pigsighv = 0, *pigslothv = 0; GV *piggv = 0; HV *pigstash; SV **pigsvp; // printf("Creating QMetaObject for %s which isa %s\n", 0, pig1->className()); objectDict->remove(pig0); pigstash = gv_stashpv((char *)pig0, TRUE); pigsvp = hv_fetch(pigstash, (char *)".signals", 8, FALSE); if(pigsvp) pigsighv = GvHV(*pigsvp); pigsvp = hv_fetch(pigstash, (char *)".slots", 6, FALSE); if(pigsvp) pigslothv = GvHV(*pigsvp); pigsigmeta = pig_createMetaData(pigsighv, FALSE, &pigsigcnt); pigslotmeta = pig_createMetaData(pigslothv, TRUE, &pigslotcnt); return new QMetaObject(pig0, pig1->className(), pigslotmeta, pigslotcnt, pigsigmeta, pigsigcnt); } PIG_DEFINE_FUNC_1(class QMetaObject *, pig_initMetaObject, const char *) { AV *pigav_isa; SV **pigsvp_isa; I32 pigcnt_isa, pigidx; const char *pigsuper = 0; { HV *pigstash = gv_stashpv((char *)pig0, TRUE); pigsvp_isa = hv_fetch(pigstash, (char *)"ISA", 3, FALSE); pigav_isa = GvAV((GV *)*pigsvp_isa); if(!pigav_isa) return 0; } pigcnt_isa = AvFILL(pigav_isa); pigsvp_isa = AvARRAY(pigav_isa); for(pigidx = 0; pigidx <= pigcnt_isa; pigidx++) { if(pig_class_isa(gv_stashsv(*pigsvp_isa, FALSE), pig_map_class("QObject"))) { STRLEN n_a; pigsuper = SvPV(*pigsvp_isa, n_a); break; } pigsvp_isa++; } if(!pigsuper) return 0; class QMetaObject *pigsupermeta = objectDict->find(pig_unmap_class(pigsuper)); if(!pigsupermeta) pigsupermeta = pig_initMetaObject(pigsuper); return pig_createMetaObject(pig0, pigsupermeta); } const char * pig_virtual_QObject__className(const pig_virtual *pig0) { return HvNAME(SvSTASH(SvRV((SV *)pig0->pig_rv))); } class QMetaObject * pig_virtual_QObject__metaObject(const pig_virtual *pig0) { // pig_object_data *pigd = pig_object_extract((SV *)pig0->pig_rv); //warn("metaobject\n"); //warn("metaobject of %s\n", pigd->piginfo->pig_classname); //warn("Going to return %p\n", objectDict->find(pigd->piginfo->pig_classname)); class QMetaObject *pigm; const char *pigclass; pigclass = pig_unmap_class(HvNAME(SvSTASH(SvRV((SV *)pig0->pig_rv)))); //printf("Okay, %p, %p, %p, %s\n", pig0->pig_rv, SvRV((SV *)pig0->pig_rv), SvSTASH(SvRV((SV *)pig0->pig_rv)), HvNAME(SvSTASH(SvRV((SV *)pig0->pig_rv)))); pigm = objectDict->find(pigclass); if(!pigm) pigm = pig_initMetaObject(pigclass); return pigm; } PIG_EXPORT_TABLE(pigobject) PIG_EXPORT_FUNC(pig_receiver_defined) PIG_EXPORT_FUNC(pig_create_slot) PIG_EXPORT_FUNC(pig_member_string) PIG_EXPORT_FUNC(pig_new_castobject) PIG_EXPORT_FUNC(pig_type_new_castobject_return) PIG_EXPORT_FUNC(pig_type_new_object_return) PIG_EXPORT_FUNC(pig_type_object_destructor_argument) PIG_EXPORT_FUNC(pig_object_destroy) PIG_EXPORT_FUNC(pig_createMetaObject) PIG_EXPORT_FUNC(pig_initMetaObject) PIG_EXPORT_FUNC(pig_sigslot_hash) PIG_EXPORT_FUNC(pig_sigslot_stub) PIG_EXPORT_ENDTABLE