summaryrefslogtreecommitdiffstats
path: root/PerlQt/Qt.xs
diff options
context:
space:
mode:
Diffstat (limited to 'PerlQt/Qt.xs')
-rw-r--r--PerlQt/Qt.xs2198
1 files changed, 0 insertions, 2198 deletions
diff --git a/PerlQt/Qt.xs b/PerlQt/Qt.xs
deleted file mode 100644
index 22a66de..0000000
--- a/PerlQt/Qt.xs
+++ /dev/null
@@ -1,2198 +0,0 @@
-#include <stdio.h>
-#include <qglobal.h>
-#include <qstring.h>
-#include <qapplication.h>
-#include <qmetaobject.h>
-#include <private/qucomextra_p.h>
-#include "smoke.h"
-
-#undef DEBUG
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#ifndef __USE_POSIX
-#define __USE_POSIX
-#endif
-#ifndef __USE_XOPEN
-#define __USE_XOPEN
-#endif
-#ifdef _BOOL
-#define HAS_BOOL
-#endif
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-#ifndef TQT_VERSION_STR
-#define TQT_VERSION_STR "Unknown"
-#endif
-
-#undef free
-#undef malloc
-
-#include "marshall.h"
-#include "perlqt.h"
-#include "smokeperl.h"
-
-#ifndef IN_BYTES
-#define IN_BYTES IN_BYTE
-#endif
-
-#ifndef IN_LOCALE
-#define IN_LOCALE (PL_curcop->op_private & HINT_LOCALE)
-#endif
-
-extern Smoke *qt_Smoke;
-extern void init_qt_Smoke();
-
-int do_debug = qtdb_none;
-
-HV *pointer_map = 0;
-SV *sv_qapp = 0;
-int object_count = 0;
-void *_current_object = 0; // TODO: ask myself if this is stupid
-
-bool temporary_virtual_function_success = false;
-
-static TQAsciiDict<Smoke::Index> *methcache = 0;
-static TQAsciiDict<Smoke::Index> *classcache = 0;
-
-SV *sv_this = 0;
-
-Smoke::Index _current_object_class = 0;
-Smoke::Index _current_method = 0;
-/*
- * Type handling by moc is simple.
- *
- * If the type name matches /^(?:const\s+)?\Q$types\E&?$/, use the
- * static_TQUType, where $types is join('|', qw(bool int double char* TQString);
- *
- * Everything else is passed as a pointer! There are types which aren't
- * Smoke::tf_ptr but will have to be passed as a pointer. Make sure to keep
- * track of what's what.
- */
-
-/*
- * Simply using typeids isn't enough for signals/slots. It will be possible
- * to declare signals and slots which use arguments which can't all be
- * found in a single smoke object. Instead, we need to store smoke => typeid
- * pairs. We also need additional informatation, such as whether we're passing
- * a pointer to the union element.
- */
-
-enum MocArgumentType {
- xmoc_ptr,
- xmoc_bool,
- xmoc_int,
- xmoc_double,
- xmoc_charstar,
- xmoc_TQString
-};
-
-struct MocArgument {
- // smoke object and associated typeid
- SmokeType st;
- MocArgumentType argType;
-};
-
-
-extern TypeHandler TQt_handlers[];
-void install_handlers(TypeHandler *);
-
-void *sv_to_ptr(SV *sv) { // ptr on success, null on fail
- smokeperl_object *o = sv_obj_info(sv);
- return o ? o->ptr : 0;
-}
-
-bool isTQObject(Smoke *smoke, Smoke::Index classId) {
- if(!strcmp(smoke->classes[classId].className, "TQObject"))
- return true;
- for(Smoke::Index *p = smoke->inheritanceList + smoke->classes[classId].parents;
- *p;
- p++) {
- if(isTQObject(smoke, *p))
- return true;
- }
- return false;
-}
-
-int isDerivedFrom(Smoke *smoke, Smoke::Index classId, Smoke::Index baseId, int cnt) {
- if(classId == baseId)
- return cnt;
- cnt++;
- for(Smoke::Index *p = smoke->inheritanceList + smoke->classes[classId].parents;
- *p;
- p++) {
- if(isDerivedFrom(smoke, *p, baseId, cnt) != -1)
- return cnt;
- }
- return -1;
-}
-
-int isDerivedFrom(Smoke *smoke, const char *className, const char *baseClassName, int cnt) {
- if(!smoke || !className || !baseClassName)
- return -1;
- Smoke::Index idClass = smoke->idClass(className);
- Smoke::Index idBase = smoke->idClass(baseClassName);
- return isDerivedFrom(smoke, idClass, idBase, cnt);
-}
-
-SV *getPointerObject(void *ptr) {
- HV *hv = pointer_map;
- SV *keysv = newSViv((IV)ptr);
- STRLEN len;
- char *key = SvPV(keysv, len);
- SV **svp = hv_fetch(hv, key, len, 0);
- if(!svp){
- SvREFCNT_dec(keysv);
- return 0;
- }
- if(!SvOK(*svp)){
- hv_delete(hv, key, len, G_DISCARD);
- SvREFCNT_dec(keysv);
- return 0;
- }
- return *svp;
-}
-
-void unmapPointer(smokeperl_object *o, Smoke::Index classId, void *lastptr) {
- HV *hv = pointer_map;
- void *ptr = o->smoke->cast(o->ptr, o->classId, classId);
- if(ptr != lastptr) {
- lastptr = ptr;
- SV *keysv = newSViv((IV)ptr);
- STRLEN len;
- char *key = SvPV(keysv, len);
- if(hv_exists(hv, key, len))
- hv_delete(hv, key, len, G_DISCARD);
- SvREFCNT_dec(keysv);
- }
- for(Smoke::Index *i = o->smoke->inheritanceList + o->smoke->classes[classId].parents;
- *i;
- i++) {
- unmapPointer(o, *i, lastptr);
- }
-}
-
-// Store pointer in pointer_map hash : "pointer_to_TQt_object" => weak ref to associated Perl object
-// Recurse to store it also as casted to its parent classes.
-
-void mapPointer(SV *obj, smokeperl_object *o, HV *hv, Smoke::Index classId, void *lastptr) {
- void *ptr = o->smoke->cast(o->ptr, o->classId, classId);
- if(ptr != lastptr) {
- lastptr = ptr;
- SV *keysv = newSViv((IV)ptr);
- STRLEN len;
- char *key = SvPV(keysv, len);
- SV *rv = newSVsv(obj);
- sv_rvweaken(rv); // weak reference!
- hv_store(hv, key, len, rv, 0);
- SvREFCNT_dec(keysv);
- }
- for(Smoke::Index *i = o->smoke->inheritanceList + o->smoke->classes[classId].parents;
- *i;
- i++) {
- mapPointer(obj, o, hv, *i, lastptr);
- }
-}
-
-Marshall::HandlerFn getMarshallFn(const SmokeType &type);
-
-class VirtualMethodReturnValue : public Marshall {
- Smoke *_smoke;
- Smoke::Index _method;
- Smoke::Stack _stack;
- SmokeType _st;
- SV *_retval;
-public:
- const Smoke::Method &method() { return _smoke->methods[_method]; }
- SmokeType type() { return _st; }
- Marshall::Action action() { return Marshall::FromSV; }
- Smoke::StackItem &item() { return _stack[0]; }
- SV *var() { return _retval; }
- void unsupported() {
- croak("Cannot handle '%s' as return-type of virtual method %s::%s",
- type().name(),
- _smoke->className(method().classId),
- _smoke->methodNames[method().name]);
- }
- Smoke *smoke() { return _smoke; }
- void next() {}
- bool cleanup() { return false; }
- VirtualMethodReturnValue(Smoke *smoke, Smoke::Index meth, Smoke::Stack stack, SV *retval) :
- _smoke(smoke), _method(meth), _stack(stack), _retval(retval) {
- _st.set(_smoke, method().ret);
- Marshall::HandlerFn fn = getMarshallFn(type());
- (*fn)(this);
- }
-};
-
-class VirtualMethodCall : public Marshall {
- Smoke *_smoke;
- Smoke::Index _method;
- Smoke::Stack _stack;
- GV *_gv;
- int _cur;
- Smoke::Index *_args;
- SV **_sp;
- bool _called;
- SV *_savethis;
-
-public:
- SmokeType type() { return SmokeType(_smoke, _args[_cur]); }
- Marshall::Action action() { return Marshall::ToSV; }
- Smoke::StackItem &item() { return _stack[_cur + 1]; }
- SV *var() { return _sp[_cur]; }
- const Smoke::Method &method() { return _smoke->methods[_method]; }
- void unsupported() {
- croak("Cannot handle '%s' as argument of virtual method %s::%s",
- type().name(),
- _smoke->className(method().classId),
- _smoke->methodNames[method().name]);
- }
- Smoke *smoke() { return _smoke; }
- void callMethod() {
- dSP;
- if(_called) return;
- _called = true;
- SP = _sp + method().numArgs - 1;
- PUTBACK;
- int count = call_sv((SV*)GvCV(_gv), G_SCALAR);
- SPAGAIN;
- VirtualMethodReturnValue r(_smoke, _method, _stack, POPs);
- PUTBACK;
- FREETMPS;
- LEAVE;
- }
- void next() {
- int oldcur = _cur;
- _cur++;
- while(!_called && _cur < method().numArgs) {
- Marshall::HandlerFn fn = getMarshallFn(type());
- (*fn)(this);
- _cur++;
- }
- callMethod();
- _cur = oldcur;
- }
- bool cleanup() { return false; } // is this right?
- VirtualMethodCall(Smoke *smoke, Smoke::Index meth, Smoke::Stack stack, SV *obj, GV *gv) :
- _smoke(smoke), _method(meth), _stack(stack), _gv(gv), _cur(-1), _sp(0), _called(false) {
- dSP;
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
- EXTEND(SP, method().numArgs);
- _savethis = sv_this;
- sv_this = newSVsv(obj);
- _sp = SP + 1;
- for(int i = 0; i < method().numArgs; i++)
- _sp[i] = sv_newmortal();
- _args = _smoke->argumentList + method().args;
- }
- ~VirtualMethodCall() {
- SvREFCNT_dec(sv_this);
- sv_this = _savethis;
- }
-};
-
-class MethodReturnValue : public Marshall {
- Smoke *_smoke;
- Smoke::Index _method;
- SV *_retval;
- Smoke::Stack _stack;
-public:
- MethodReturnValue(Smoke *smoke, Smoke::Index method, Smoke::Stack stack, SV *retval) :
- _smoke(smoke), _method(method), _retval(retval), _stack(stack) {
- Marshall::HandlerFn fn = getMarshallFn(type());
- (*fn)(this);
- }
- const Smoke::Method &method() { return _smoke->methods[_method]; }
- SmokeType type() { return SmokeType(_smoke, method().ret); }
- Marshall::Action action() { return Marshall::ToSV; }
- Smoke::StackItem &item() { return _stack[0]; }
- SV *var() { return _retval; }
- void unsupported() {
- croak("Cannot handle '%s' as return-type of %s::%s",
- type().name(),
- _smoke->className(method().classId),
- _smoke->methodNames[method().name]);
- }
- Smoke *smoke() { return _smoke; }
- void next() {}
- bool cleanup() { return false; }
-};
-
-class MethodCall : public Marshall {
- int _cur;
- Smoke *_smoke;
- Smoke::Stack _stack;
- Smoke::Index _method;
- Smoke::Index *_args;
- SV **_sp;
- int _items;
- SV *_retval;
- bool _called;
-public:
- MethodCall(Smoke *smoke, Smoke::Index method, SV **sp, int items) :
- _smoke(smoke), _method(method), _sp(sp), _items(items), _cur(-1), _called(false) {
- _args = _smoke->argumentList + _smoke->methods[_method].args;
- _items = _smoke->methods[_method].numArgs;
- _stack = new Smoke::StackItem[items + 1];
- _retval = newSV(0);
- }
- ~MethodCall() {
- delete[] _stack;
- SvREFCNT_dec(_retval);
- }
- SmokeType type() { return SmokeType(_smoke, _args[_cur]); }
- Marshall::Action action() { return Marshall::FromSV; }
- Smoke::StackItem &item() { return _stack[_cur + 1]; }
- SV *var() {
- if(_cur < 0) return _retval;
- SvGETMAGIC(*(_sp + _cur));
- return *(_sp + _cur);
- }
- inline const Smoke::Method &method() { return _smoke->methods[_method]; }
- void unsupported() {
- croak("Cannot handle '%s' as argument to %s::%s",
- type().name(),
- _smoke->className(method().classId),
- _smoke->methodNames[method().name]);
- }
- Smoke *smoke() { return _smoke; }
- inline void callMethod() {
- if(_called) return;
- _called = true;
- Smoke::ClassFn fn = _smoke->classes[method().classId].classFn;
- void *ptr = _smoke->cast(
- _current_object,
- _current_object_class,
- method().classId
- );
- _items = -1;
- (*fn)(method().method, ptr, _stack);
- MethodReturnValue r(_smoke, _method, _stack, _retval);
- }
- void next() {
- int oldcur = _cur;
- _cur++;
-
- while(!_called && _cur < _items) {
- Marshall::HandlerFn fn = getMarshallFn(type());
- (*fn)(this);
- _cur++;
- }
-
- callMethod();
- _cur = oldcur;
- }
- bool cleanup() { return true; }
-};
-
-class UnencapsulatedTQObject : public TQObject {
-public:
- TQConnectionList *public_receivers(int signal) const { return receivers(signal); }
- void public_activate_signal(TQConnectionList *clist, TQUObject *o) { activate_signal(clist, o); }
-};
-
-class EmitSignal : public Marshall {
- UnencapsulatedTQObject *_qobj;
- int _id;
- MocArgument *_args;
- SV **_sp;
- int _items;
- int _cur;
- Smoke::Stack _stack;
- bool _called;
-public:
- EmitSignal(TQObject *qobj, int id, int items, MocArgument *args, SV **sp) :
- _qobj((UnencapsulatedTQObject*)qobj), _id(id), _items(items), _args(args),
- _sp(sp), _cur(-1), _called(false) {
- _stack = new Smoke::StackItem[_items];
- }
- ~EmitSignal() {
- delete[] _stack;
- }
- const MocArgument &arg() { return _args[_cur]; }
- SmokeType type() { return arg().st; }
- Marshall::Action action() { return Marshall::FromSV; }
- Smoke::StackItem &item() { return _stack[_cur]; }
- SV *var() { return _sp[_cur]; }
- void unsupported() {
- croak("Cannot handle '%s' as signal argument", type().name());
- }
- Smoke *smoke() { return type().smoke(); }
- void emitSignal() {
- if(_called) return;
- _called = true;
-
- TQConnectionList *clist = _qobj->public_receivers(_id);
- if(!clist) return;
-
- TQUObject *o = new TQUObject[_items + 1];
- for(int i = 0; i < _items; i++) {
- TQUObject *po = o + i + 1;
- Smoke::StackItem *si = _stack + i;
- switch(_args[i].argType) {
- case xmoc_bool:
- static_TQUType_bool.set(po, si->s_bool);
- break;
- case xmoc_int:
- static_TQUType_int.set(po, si->s_int);
- break;
- case xmoc_double:
- static_TQUType_double.set(po, si->s_double);
- break;
- case xmoc_charstar:
- static_TQUType_charstar.set(po, (char*)si->s_voidp);
- break;
- case xmoc_TQString:
- static_TQUType_TQString.set(po, *(TQString*)si->s_voidp);
- break;
- default:
- {
- const SmokeType &t = _args[i].st;
- void *p;
- switch(t.elem()) {
- case Smoke::t_bool:
- p = &si->s_bool;
- break;
- case Smoke::t_char:
- p = &si->s_char;
- break;
- case Smoke::t_uchar:
- p = &si->s_uchar;
- break;
- case Smoke::t_short:
- p = &si->s_short;
- break;
- case Smoke::t_ushort:
- p = &si->s_ushort;
- break;
- case Smoke::t_int:
- p = &si->s_int;
- break;
- case Smoke::t_uint:
- p = &si->s_uint;
- break;
- case Smoke::t_long:
- p = &si->s_long;
- break;
- case Smoke::t_ulong:
- p = &si->s_ulong;
- break;
- case Smoke::t_float:
- p = &si->s_float;
- break;
- case Smoke::t_double:
- p = &si->s_double;
- break;
- case Smoke::t_enum:
- {
- // allocate a new enum value
- Smoke::EnumFn fn = SmokeClass(t).enumFn();
- if(!fn) {
- warn("Unknown enumeration %s\n", t.name());
- p = new int((int)si->s_enum);
- break;
- }
- Smoke::Index id = t.typeId();
- (*fn)(Smoke::EnumNew, id, p, si->s_enum);
- (*fn)(Smoke::EnumFromLong, id, p, si->s_enum);
- // FIXME: MEMORY LEAK
- }
- break;
- case Smoke::t_class:
- case Smoke::t_voidp:
- p = si->s_voidp;
- break;
- default:
- p = 0;
- break;
- }
- static_TQUType_ptr.set(po, p);
- }
- }
- }
-
- _qobj->public_activate_signal(clist, o);
- delete[] o;
- }
- void next() {
- int oldcur = _cur;
- _cur++;
-
- while(!_called && _cur < _items) {
- Marshall::HandlerFn fn = getMarshallFn(type());
- (*fn)(this);
- _cur++;
- }
-
- emitSignal();
- _cur = oldcur;
- }
- bool cleanup() { return true; }
-};
-
-class InvokeSlot : public Marshall {
- TQObject *_qobj;
- GV *_gv;
- int _items;
- MocArgument *_args;
- TQUObject *_o;
- int _cur;
- bool _called;
- SV **_sp;
- Smoke::Stack _stack;
-public:
- const MocArgument &arg() { return _args[_cur]; }
- SmokeType type() { return arg().st; }
- Marshall::Action action() { return Marshall::ToSV; }
- Smoke::StackItem &item() { return _stack[_cur]; }
- SV *var() { return _sp[_cur]; }
- Smoke *smoke() { return type().smoke(); }
- bool cleanup() { return false; }
- void unsupported() {
- croak("Cannot handle '%s' as slot argument\n", type().name());
- }
- void copyArguments() {
- for(int i = 0; i < _items; i++) {
- TQUObject *o = _o + i + 1;
- switch(_args[i].argType) {
- case xmoc_bool:
- _stack[i].s_bool = static_TQUType_bool.get(o);
- break;
- case xmoc_int:
- _stack[i].s_int = static_TQUType_int.get(o);
- break;
- case xmoc_double:
- _stack[i].s_double = static_TQUType_double.get(o);
- break;
- case xmoc_charstar:
- _stack[i].s_voidp = static_TQUType_charstar.get(o);
- break;
- case xmoc_TQString:
- _stack[i].s_voidp = &static_TQUType_TQString.get(o);
- break;
- default: // case xmoc_ptr:
- {
- const SmokeType &t = _args[i].st;
- void *p = static_TQUType_ptr.get(o);
- switch(t.elem()) {
- case Smoke::t_bool:
- _stack[i].s_bool = *(bool*)p;
- break;
- case Smoke::t_char:
- _stack[i].s_char = *(char*)p;
- break;
- case Smoke::t_uchar:
- _stack[i].s_uchar = *(unsigned char*)p;
- break;
- case Smoke::t_short:
- _stack[i].s_short = *(short*)p;
- break;
- case Smoke::t_ushort:
- _stack[i].s_ushort = *(unsigned short*)p;
- break;
- case Smoke::t_int:
- _stack[i].s_int = *(int*)p;
- break;
- case Smoke::t_uint:
- _stack[i].s_uint = *(unsigned int*)p;
- break;
- case Smoke::t_long:
- _stack[i].s_long = *(long*)p;
- break;
- case Smoke::t_ulong:
- _stack[i].s_ulong = *(unsigned long*)p;
- break;
- case Smoke::t_float:
- _stack[i].s_float = *(float*)p;
- break;
- case Smoke::t_double:
- _stack[i].s_double = *(double*)p;
- break;
- case Smoke::t_enum:
- {
- Smoke::EnumFn fn = SmokeClass(t).enumFn();
- if(!fn) {
- warn("Unknown enumeration %s\n", t.name());
- _stack[i].s_enum = *(int*)p;
- break;
- }
- Smoke::Index id = t.typeId();
- (*fn)(Smoke::EnumToLong, id, p, _stack[i].s_enum);
- }
- break;
- case Smoke::t_class:
- case Smoke::t_voidp:
- _stack[i].s_voidp = p;
- break;
- }
- }
- }
- }
- }
- void invokeSlot() {
- dSP;
- if(_called) return;
- _called = true;
-
- SP = _sp + _items - 1;
- PUTBACK;
- int count = call_sv((SV*)GvCV(_gv), G_SCALAR);
- SPAGAIN;
- SP -= count;
- PUTBACK;
- FREETMPS;
- LEAVE;
- }
- void next() {
- int oldcur = _cur;
- _cur++;
-
- while(!_called && _cur < _items) {
- Marshall::HandlerFn fn = getMarshallFn(type());
- (*fn)(this);
- _cur++;
- }
-
- invokeSlot();
- _cur = oldcur;
- }
- InvokeSlot(TQObject *qobj, GV *gv, int items, MocArgument *args, TQUObject *o) :
- _qobj(qobj), _gv(gv), _items(items), _args(args), _o(o), _cur(-1), _called(false) {
- dSP;
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
- EXTEND(SP, items);
- PUTBACK;
- _sp = SP + 1;
- for(int i = 0; i < _items; i++)
- _sp[i] = sv_newmortal();
- _stack = new Smoke::StackItem[_items];
- copyArguments();
- }
- ~InvokeSlot() {
- delete[] _stack;
- }
-
-};
-
-class TQtSmokeBinding : public SmokeBinding {
-public:
- TQtSmokeBinding(Smoke *s) : SmokeBinding(s) {}
- void deleted(Smoke::Index classId, void *ptr) {
- SV *obj = getPointerObject(ptr);
- smokeperl_object *o = sv_obj_info(obj);
- if(do_debug && (do_debug & qtdb_gc)) {
- fprintf(stderr, "%p->~%s()\n", ptr, smoke->className(classId));
- }
- if(!o || !o->ptr) {
- return;
- }
- unmapPointer(o, o->classId, 0);
- o->ptr = 0;
- }
- bool callMethod(Smoke::Index method, void *ptr, Smoke::Stack args, bool isAbstract) {
- SV *obj = getPointerObject(ptr);
- smokeperl_object *o = sv_obj_info(obj);
- if(do_debug && (do_debug & qtdb_virtual)) fprintf(stderr, "virtual %p->%s::%s() called\n", ptr,
- smoke->classes[smoke->methods[method].classId].className,
- smoke->methodNames[smoke->methods[method].name]
- );
-
- if(!o) {
- if(!PL_dirty && (do_debug && (do_debug & qtdb_virtual)) ) // if not in global destruction
- fprintf(stderr, "Cannot find object for virtual method\n");
- return false;
- }
- HV *stash = SvSTASH(SvRV(obj));
- if(*HvNAME(stash) == ' ')
- stash = gv_stashpv(HvNAME(stash) + 1, TRUE);
- const char *methodName = smoke->methodNames[smoke->methods[method].name];
- GV *gv = gv_fetchmethod_autoload(stash, methodName, 0);
- if(!gv) return false;
-
- VirtualMethodCall c(smoke, method, args, obj, gv);
- // exception variable, just temporary
- temporary_virtual_function_success = true;
- c.next();
- bool ret = temporary_virtual_function_success;
- temporary_virtual_function_success = true;
- return ret;
- }
- char *className(Smoke::Index classId) {
- const char *className = smoke->className(classId);
- char *buf = new char[strlen(className) + 6];
- strcpy(buf, " TQt::");
- strcat(buf, className + 1);
- return buf;
- }
-};
-
-// ---------------- Helpers -------------------
-
-SV *catArguments(SV** sp, int n)
-{
- SV* r=newSVpvf("");
- for(int i = 0; i < n; i++) {
- if(i) sv_catpv(r, ", ");
- if(!SvOK(sp[i])) {
- sv_catpv(r, "undef");
- } else if(SvROK(sp[i])) {
- smokeperl_object *o = sv_obj_info(sp[i]);
- if(o)
- sv_catpv(r, o->smoke->className(o->classId));
- else
- sv_catsv(r, sp[i]);
- } else {
- bool isString = SvPOK(sp[i]);
- STRLEN len;
- char *s = SvPV(sp[i], len);
- if(isString) sv_catpv(r, "'");
- sv_catpvn(r, s, len > 10 ? 10 : len);
- if(len > 10) sv_catpv(r, "...");
- if(isString) sv_catpv(r, "'");
- }
- }
- return r;
-}
-
-Smoke::Index package_classid(const char *p)
-{
- Smoke::Index *item = classcache->find(p);
- if(item)
- return *item;
- char *nisa = new char[strlen(p)+6];
- strcpy(nisa, p);
- strcat(nisa, "::ISA");
- AV* isa=get_av(nisa, true);
- delete[] nisa;
- for(int i=0; i<=av_len(isa); i++) {
- SV** np = av_fetch(isa, i, 0);
- if(np) {
- Smoke::Index ix = package_classid(SvPV_nolen(*np));
- if(ix) {
- classcache->insert(p, new Smoke::Index(ix));
- return ix;
- }
- }
- }
- return (Smoke::Index) 0;
-}
-
-char *get_SVt(SV *sv)
-{
- char *r;
- if(!SvOK(sv))
- r = "u";
- else if(SvIOK(sv))
- r = "i";
- else if(SvNOK(sv))
- r = "n";
- else if(SvPOK(sv))
- r = "s";
- else if(SvROK(sv)) {
- smokeperl_object *o = sv_obj_info(sv);
- if(!o) {
- switch (SvTYPE(SvRV(sv))) {
- case SVt_PVAV:
- r = "a";
- break;
-// case SVt_PV:
-// case SVt_PVMG:
-// r = "p";
- default:
- r = "r";
- }
- }
- else
- r = (char*)o->smoke->className(o->classId);
- }
- else
- r = "U";
- return r;
-}
-
-SV *prettyPrintMethod(Smoke::Index id) {
- SV *r = newSVpvf("");
- Smoke::Method &meth = qt_Smoke->methods[id];
- const char *tname = qt_Smoke->types[meth.ret].name;
- if(meth.flags & Smoke::mf_static) sv_catpv(r, "static ");
- sv_catpvf(r, "%s ", (tname ? tname:"void"));
- sv_catpvf(r, "%s::%s(", qt_Smoke->classes[meth.classId].className, qt_Smoke->methodNames[meth.name]);
- for(int i = 0; i < meth.numArgs; i++) {
- if(i) sv_catpv(r, ", ");
- tname = qt_Smoke->types[qt_Smoke->argumentList[meth.args+i]].name;
- sv_catpv(r, (tname ? tname:"void"));
- }
- sv_catpv(r, ")");
- if(meth.flags & Smoke::mf_const) sv_catpv(r, " const");
- return r;
-}
-
-// --------------- Unary Keywords && Attributes ------------------
-
-
-// implements unary 'this'
-XS(XS_this) {
- dXSARGS;
- ST(0) = sv_this;
- XSRETURN(1);
-}
-
-// implements unary attributes: 'foo' means 'this->{foo}'
-XS(XS_attr) {
- dXSARGS;
- char *key = GvNAME(CvGV(cv));
- U32 klen = strlen(key);
- SV **svp = 0;
- if(SvROK(sv_this) && SvTYPE(SvRV(sv_this)) == SVt_PVHV) {
- HV *hv = (HV*)SvRV(sv_this);
- svp = hv_fetch(hv, key, klen, 1);
- }
- if(svp) {
- ST(0) = *svp;
- XSRETURN(1);
- }
- XSRETURN_UNDEF;
-}
-
-// implements unary SUPER attribute: 'SUPER' means ${(CopSTASH)::_INTERNAL_STATIC_}{SUPER}
-XS(XS_super) {
- dXSARGS;
- char *key = "SUPER";
- U32 klen = strlen(key);
- SV **svp = 0;
- if(SvROK(sv_this) && SvTYPE(SvRV(sv_this)) == SVt_PVHV) {
- HV *cs = (HV*)CopSTASH(PL_curcop);
- if(!cs) XSRETURN_UNDEF;
- svp = hv_fetch(cs, "_INTERNAL_STATIC_", 17, 0);
- if(!svp) XSRETURN_UNDEF;
- cs = GvHV((GV*)*svp);
- if(!cs) XSRETURN_UNDEF;
- svp = hv_fetch(cs, "SUPER", 5, 0);
- }
- if(svp) {
- ST(0) = *svp;
- XSRETURN(1);
- }
- XSRETURN_UNDEF;
-}
-
-//---------- XS Autoload (for all functions except fully qualified statics & enums) ---------
-
-static inline bool isTQt(char *p) {
- return (p[0] == 'Q' && p[1] && p[1] == 't' && ((p[2] && p[2] == ':') || !p[2]));
-}
-
-bool avoid_fetchmethod = false;
-XS(XS_AUTOLOAD) {
- // Err, XS autoload is borked. Lets try...
- dXSARGS;
- SV *sv = get_sv("TQt::AutoLoad::AUTOLOAD", TRUE);
- char *package = SvPV_nolen(sv);
- char *method = 0;
- for(char *s = package; *s ; s++)
- if(*s == ':') method = s;
- if(!method) XSRETURN_NO;
- *(method++ - 1) = 0; // sorry for showing off. :)
- int withObject = (*package == ' ') ? 1 : 0;
- int isSuper = 0;
- if(withObject) {
- package++;
- if(*package == ' ') {
- isSuper = 1;
- char *super = new char[strlen(package) + 7];
- package++;
- strcpy(super, package);
- strcat(super, "::SUPER");
- package = super;
- }
- } else if( isTQt(package) )
- avoid_fetchmethod = true;
-
- HV *stash = gv_stashpv(package, TRUE);
-
- if(do_debug && (do_debug & qtdb_autoload))
- warn("In XS Autoload for %s::%s()\n", package, method);
-
- // check for user-defined methods in the REAL stash; skip prefix
- GV *gv = 0;
- if(avoid_fetchmethod)
- avoid_fetchmethod = false;
- else
- gv = gv_fetchmethod_autoload(stash, method, 0);
-
- // If we've made it here, we need to set sv_this
- if(gv) {
- if(do_debug && (do_debug & qtdb_autoload))
- warn("\tfound in %s's Perl stash\n", package);
-
- // call the defined Perl method with new 'this'
- SV *old_this;
- if(withObject && !isSuper) {
- old_this = sv_this;
- sv_this = newSVsv(ST(0));
- }
-
- ENTER;
- SAVETMPS;
- PUSHMARK(SP - items + withObject);
- PUTBACK;
- int count = call_sv((SV*)GvCV(gv), G_SCALAR|G_EVAL);
- SPAGAIN;
- SV *ret = newSVsv(TOPs);
- SP -= count;
- PUTBACK;
- FREETMPS;
- LEAVE;
-
- if(withObject && !isSuper) {
- SvREFCNT_dec(sv_this);
- sv_this = old_this;
- }
- else if(isSuper)
- delete[] package;
-
- if(SvTRUE(ERRSV))
- croak(SvPV_nolen(ERRSV));
- ST(0) = sv_2mortal(ret);
- XSRETURN(1);
- }
- else if(!strcmp(method, "DESTROY")) {
- SV *old_this;
- if(withObject && !isSuper) {
- old_this = sv_this;
- sv_this = newSVsv(ST(0));
- }
- smokeperl_object *o = sv_obj_info(sv_this);
-
- if(!(o && o->ptr && (o->allocated || getPointerObject(o->ptr)))) {
- if(isSuper)
- delete[] package;
- if(withObject && !isSuper) {
- SvREFCNT_dec(sv_this);
- sv_this = old_this;
- }
- XSRETURN_YES;
- }
- const char *key = "has been hidden";
- U32 klen = 15;
- SV **svp = 0;
- if(SvROK(sv_this) && SvTYPE(SvRV(sv_this)) == SVt_PVHV) {
- HV *hv = (HV*)SvRV(sv_this);
- svp = hv_fetch(hv, key, klen, 0);
- }
- if(svp) {
- if(isSuper)
- delete[] package;
- if(withObject && !isSuper) {
- SvREFCNT_dec(sv_this);
- sv_this = old_this;
- }
- XSRETURN_YES;
- }
- gv = gv_fetchmethod_autoload(stash, "ON_DESTROY", 0);
- if( !gv )
- croak( "Couldn't find ON_DESTROY method for %s=%p\n", package, o->ptr);
- PUSHMARK(SP);
- call_sv((SV*)GvCV(gv), G_SCALAR|G_NOARGS);
- SPAGAIN;
- int ret = POPi;
- PUTBACK;
- if(withObject && !isSuper) {
- SvREFCNT_dec(sv_this);
- sv_this = old_this;
- }
- if( do_debug && ret && (do_debug & qtdb_gc) )
- fprintf(stderr, "Increasing refcount in DESTROY for %s=%p (still has a parent)\n", package, o->ptr);
- } else {
-
- if( items > 18 ) XSRETURN_NO; // current max number of args in TQt is 13.
-
- // save the stack -- we'll need it
- SV **savestack = new SV*[items+1];
- SV *saveobj = ST(0);
- SV *old_this;
-
- Copy(SP - items + 1 + withObject, savestack, items-withObject, SV*);
-
- // Get the classid (eventually converting SUPER to the right TQt class)
- Smoke::Index cid = package_classid(package);
- // Look in the cache
- char *cname = (char*)qt_Smoke->className(cid);
- int lcname = strlen(cname);
- int lmethod = strlen(method);
- char mcid[256];
- strncpy(mcid, cname, lcname);
- char *ptr = mcid + lcname;
- *(ptr++) = ';';
- strncpy(ptr, method, lmethod);
- ptr += lmethod;
- for(int i=withObject ; i<items ; i++)
- {
- *(ptr++) = ';';
- char *t = get_SVt(ST(i));
- int tlen = strlen(t);
- strncpy(ptr, t, tlen );
- ptr += tlen;
- }
- *ptr = 0;
- Smoke::Index *rcid = methcache->find(mcid);
-
- if(rcid) {
- // Got a hit
- _current_method = *rcid;
- if(withObject && !isSuper) {
- old_this = sv_this;
- sv_this = newSVsv(ST(0));
- }
- }
- else {
-
- // Find the C++ method to call. I'll do that from Perl for now
-
- ENTER;
- SAVETMPS;
- PUSHMARK(SP - items + withObject);
- EXTEND(SP, 3);
- PUSHs(sv_2mortal(newSViv((IV)cid)));
- PUSHs(sv_2mortal(newSVpv(method, 0)));
- PUSHs(sv_2mortal(newSVpv(package, 0)));
- PUTBACK;
- if(withObject && !isSuper) {
- old_this = sv_this;
- sv_this = newSVsv(saveobj);
- }
- call_pv("TQt::_internal::do_autoload", G_DISCARD|G_EVAL);
- FREETMPS;
- LEAVE;
-
- // Restore sv_this on error, so that eval{ } works
- if(SvTRUE(ERRSV)) {
- if(withObject && !isSuper) {
- SvREFCNT_dec(sv_this);
- sv_this = old_this;
- }
- else if(isSuper)
- delete[] package;
- delete[] savestack;
- croak(SvPV_nolen(ERRSV));
- }
-
- // Success. Cache result.
- methcache->insert(mcid, new Smoke::Index(_current_method));
- }
- // FIXME: I shouldn't have to set the current object
- {
- smokeperl_object *o = sv_obj_info(sv_this);
- if(o && o->ptr) {
- _current_object = o->ptr;
- _current_object_class = o->classId;
- } else {
- _current_object = 0;
- }
- }
- // honor debugging channels
- if(do_debug && (do_debug & qtdb_calls)) {
- warn("Calling method\t%s\n", SvPV_nolen(sv_2mortal(prettyPrintMethod(_current_method))));
- if(do_debug & qtdb_verbose)
- warn("with arguments (%s)\n", SvPV_nolen(sv_2mortal(catArguments(savestack, items-withObject))));
- }
- MethodCall c(qt_Smoke, _current_method, savestack, items-withObject);
- c.next();
- if(savestack)
- delete[] savestack;
-
- if(withObject && !isSuper) {
- SvREFCNT_dec(sv_this);
- sv_this = old_this;
- }
- else if(isSuper)
- delete[] package;
-
- SV *ret = c.var();
- SvREFCNT_inc(ret);
- ST(0) = sv_2mortal(ret);
- XSRETURN(1);
- }
- if(isSuper)
- delete[] package;
- XSRETURN_YES;
-}
-
-
-//----------------- Sig/Slot ------------------
-
-
-MocArgument *getmetainfo(GV *gv, const char *name, int &offset, int &index, int &argcnt) {
- char *signalname = GvNAME(gv);
- HV *stash = GvSTASH(gv);
-
- // $meta = $stash->{META}
- SV **svp = hv_fetch(stash, "META", 4, 0);
- if(!svp) return 0;
- HV *hv = GvHV((GV*)*svp);
- if(!hv) return 0;
-
- // $metaobject = $meta->{object}
- // aka. Class->staticMetaObject
- svp = hv_fetch(hv, "object", 6, 0);
- if(!svp) return 0;
- smokeperl_object *ometa = sv_obj_info(*svp);
- if(!ometa) return 0;
- TQMetaObject *metaobject = (TQMetaObject*)ometa->ptr;
-
- offset = metaobject->signalOffset();
-
- // $signals = $meta->{signal}
- U32 len = strlen(name);
- svp = hv_fetch(hv, name, len, 0);
- if(!svp) return 0;
- HV *signalshv = (HV*)SvRV(*svp);
-
- // $signal = $signals->{$signalname}
- len = strlen(signalname);
- svp = hv_fetch(signalshv, signalname, len, 0);
- if(!svp) return 0;
- HV *signalhv = (HV*)SvRV(*svp);
-
- // $index = $signal->{index}
- svp = hv_fetch(signalhv, "index", 5, 0);
- if(!svp) return 0;;
- index = SvIV(*svp);
-
- // $argcnt = $signal->{argcnt}
- svp = hv_fetch(signalhv, "argcnt", 6, 0);
- if(!svp) return 0;
- argcnt = SvIV(*svp);
-
- // $mocargs = $signal->{mocargs}
- svp = hv_fetch(signalhv, "mocargs", 7, 0);
- if(!svp) return 0;
- MocArgument *args = (MocArgument*)SvIV(*svp);
-
- return args;
-}
-
-MocArgument *getslotinfo(GV *gv, int id, char *&slotname, int &index, int &argcnt, bool isSignal = false) {
- HV *stash = GvSTASH(gv);
-
- // $meta = $stash->{META}
- SV **svp = hv_fetch(stash, "META", 4, 0);
- if(!svp) return 0;
- HV *hv = GvHV((GV*)*svp);
- if(!hv) return 0;
-
- // $metaobject = $meta->{object}
- // aka. Class->staticMetaObject
- svp = hv_fetch(hv, "object", 6, 0);
- if(!svp) return 0;
- smokeperl_object *ometa = sv_obj_info(*svp);
- if(!ometa) return 0;
- TQMetaObject *metaobject = (TQMetaObject*)ometa->ptr;
-
- int offset = isSignal ? metaobject->signalOffset() : metaobject->slotOffset();
-
- index = id - offset; // where we at
- // FIXME: make slot inheritance work
- if(index < 0) return 0;
- // $signals = $meta->{signal}
- const char *key = isSignal ? "signals" : "slots";
- svp = hv_fetch(hv, key, strlen(key), 0);
- if(!svp) return 0;
- AV *signalsav = (AV*)SvRV(*svp);
- svp = av_fetch(signalsav, index, 0);
- if(!svp) return 0;
- HV *signalhv = (HV*)SvRV(*svp);
- // $argcnt = $signal->{argcnt}
- svp = hv_fetch(signalhv, "argcnt", 6, 0);
- if(!svp) return 0;
- argcnt = SvIV(*svp);
- // $mocargs = $signal->{mocargs}
- svp = hv_fetch(signalhv, "mocargs", 7, 0);
- if(!svp) return 0;
- MocArgument *args = (MocArgument*)SvIV(*svp);
-
- svp = hv_fetch(signalhv, "name", 4, 0);
- if(!svp) return 0;
- slotname = SvPV_nolen(*svp);
-
- return args;
-}
-
-XS(XS_signal) {
- dXSARGS;
-
- smokeperl_object *o = sv_obj_info(sv_this);
- TQObject *qobj = (TQObject*)o->smoke->cast(
- o->ptr,
- o->classId,
- o->smoke->idClass("TQObject")
- );
- if(qobj->signalsBlocked()) XSRETURN_UNDEF;
-
- int offset;
- int index;
- int argcnt;
- MocArgument *args;
-
- args = getmetainfo(CvGV(cv), "signal", offset, index, argcnt);
- if(!args) XSRETURN_UNDEF;
-
- // Okay, we have the signal info. *whew*
- if(items < argcnt)
- croak("Insufficient arguments to emit signal");
-
- EmitSignal signal(qobj, offset + index, argcnt, args, &ST(0));
- signal.next();
-
- XSRETURN_UNDEF;
-}
-
-XS(XS_qt_invoke) {
- dXSARGS;
- // Arguments: int id, TQUObject *o
- int id = SvIV(ST(0));
- TQUObject *_o = (TQUObject*)SvIV(SvRV(ST(1)));
-
- smokeperl_object *o = sv_obj_info(sv_this);
- TQObject *qobj = (TQObject*)o->smoke->cast(
- o->ptr,
- o->classId,
- o->smoke->idClass("TQObject")
- );
-
- // Now, I need to find out if this means me
- int index;
- char *slotname;
- int argcnt;
- MocArgument *args;
- bool isSignal = !strcmp(GvNAME(CvGV(cv)), "qt_emit");
- args = getslotinfo(CvGV(cv), id, slotname, index, argcnt, isSignal);
- if(!args) {
- // throw an exception - evil style
- temporary_virtual_function_success = false;
- XSRETURN_UNDEF;
- }
- HV *stash = GvSTASH(CvGV(cv));
- GV *gv = gv_fetchmethod_autoload(stash, slotname, 0);
- if(!gv) XSRETURN_UNDEF;
- InvokeSlot slot(qobj, gv, argcnt, args, _o);
- slot.next();
-
- XSRETURN_UNDEF;
-}
-
-// ------------------- Tied types ------------------------
-
-MODULE = TQt PACKAGE = TQt::_internal::TQString
-PROTOTYPES: DISABLE
-
-SV*
-FETCH(obj)
- SV* obj
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQString *s = (TQString*) tmp;
- RETVAL = newSV(0);
- if( s )
- {
- if(!(IN_BYTES))
- {
- sv_setpv_mg(RETVAL, (const char *)s->utf8());
- SvUTF8_on(RETVAL);
- }
- else if(IN_LOCALE)
- sv_setpv_mg(RETVAL, (const char *)s->local8Bit());
- else
- sv_setpv_mg(RETVAL, (const char *)s->latin1());
- }
- else
- sv_setsv_mg(RETVAL, &PL_sv_undef);
- OUTPUT:
- RETVAL
-
-void
-STORE(obj,what)
- SV* obj
- SV* what
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQString *s = (TQString*) tmp;
- s->truncate(0);
- if(SvOK(what)) {
- if(SvUTF8(what))
- s->append(TQString::fromUtf8(SvPV_nolen(what)));
- else if(IN_LOCALE)
- s->append(TQString::fromLocal8Bit(SvPV_nolen(what)));
- else
- s->append(TQString::fromLatin1(SvPV_nolen(what)));
- }
-
-void
-DESTROY(obj)
- SV* obj
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQString *s = (TQString*) tmp;
- delete s;
-
-MODULE = TQt PACKAGE = TQt::_internal::TQByteArray
-PROTOTYPES: DISABLE
-
-SV*
-FETCH(obj)
- SV* obj
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQByteArray *s = (TQByteArray*) tmp;
- RETVAL = newSV(0);
- if( s )
- {
- sv_setpvn_mg(RETVAL, s->data(), s->size());
- }
- else
- sv_setsv_mg(RETVAL, &PL_sv_undef);
- OUTPUT:
- RETVAL
-
-void
-STORE(obj,what)
- SV* obj
- SV* what
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQByteArray *s = (TQByteArray*) tmp;
-
- if(SvOK(what)) {
- STRLEN len;
- char* tmp2 = SvPV(what, len);
- s->resize(len);
- Copy((void*)tmp2, (void*)s->data(), len, char);
- } else
- s->truncate(0);
-
-void
-DESTROY(obj)
- SV* obj
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQByteArray *s = (TQByteArray*) tmp;
- delete s;
-
-MODULE = TQt PACKAGE = TQt::_internal::TQRgbStar
-PROTOTYPES: DISABLE
-
-SV*
-FETCH(obj)
- SV* obj
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQRgb *s = (TQRgb*) tmp;
- AV* ar = newAV();
- RETVAL = newRV_noinc((SV*)ar);
- for(int i=0; s[i] ; i++)
- {
- SV *item = newSViv((IV)s[i]);
- if(!av_store(ar, (I32)i, item))
- SvREFCNT_dec( item );
- }
- OUTPUT:
- RETVAL
-
-void
-STORE(obj,sv)
- SV* obj
- SV* sv
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQRgb *s = (TQRgb*) tmp;
- if(!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV ||
- av_len((AV*)SvRV(sv)) < 0) {
- s = new TQRgb[1];
- s[0] = 0;
- sv_setref_pv(obj, "TQt::_internal::TQRgbStar", (void*)s);
- return;
- }
- AV *list = (AV*)SvRV(sv);
- int count = av_len(list);
- s = new TQRgb[count + 2];
- int i;
- for(i = 0; i <= count; i++) {
- SV **item = av_fetch(list, i, 0);
- if(!item || !SvOK(*item)) {
- s[i] = 0;
- continue;
- }
- s[i] = SvIV(*item);
- }
- s[i] = 0;
- sv_setref_pv(obj, "TQt::_internal::TQRgbStar", (void*)s);
-
-void
-DESTROY(obj)
- SV* obj
- CODE:
- if (!SvROK(obj))
- croak("?");
- IV tmp = SvIV((SV*)SvRV(obj));
- TQRgb *s = (TQRgb*) tmp;
- delete[] s;
-
-# --------------- XSUBS for TQt::_internal::* helpers ----------------
-
-
-MODULE = TQt PACKAGE = TQt::_internal
-PROTOTYPES: DISABLE
-
-void
-getMethStat()
- PPCODE:
- XPUSHs(sv_2mortal(newSViv((int)methcache->size())));
- XPUSHs(sv_2mortal(newSViv((int)methcache->count())));
-
-void
-getClassStat()
- PPCODE:
- XPUSHs(sv_2mortal(newSViv((int)classcache->size())));
- XPUSHs(sv_2mortal(newSViv((int)classcache->count())));
-
-void
-getIsa(classId)
- int classId
- PPCODE:
- Smoke::Index *parents =
- qt_Smoke->inheritanceList +
- qt_Smoke->classes[classId].parents;
- while(*parents)
- XPUSHs(sv_2mortal(newSVpv(qt_Smoke->classes[*parents++].className, 0)));
-
-void
-dontRecurse()
- CODE:
- avoid_fetchmethod = true;
-
-void *
-sv_to_ptr(sv)
- SV* sv
-
-void *
-allocateMocArguments(count)
- int count
- CODE:
- RETVAL = (void*)new MocArgument[count + 1];
- OUTPUT:
- RETVAL
-
-void
-setMocType(ptr, idx, name, static_type)
- void *ptr
- int idx
- char *name
- char *static_type
- CODE:
- Smoke::Index typeId = qt_Smoke->idType(name);
- if(!typeId) XSRETURN_NO;
- MocArgument *arg = (MocArgument*)ptr;
- arg[idx].st.set(qt_Smoke, typeId);
- if(!strcmp(static_type, "ptr"))
- arg[idx].argType = xmoc_ptr;
- else if(!strcmp(static_type, "bool"))
- arg[idx].argType = xmoc_bool;
- else if(!strcmp(static_type, "int"))
- arg[idx].argType = xmoc_int;
- else if(!strcmp(static_type, "double"))
- arg[idx].argType = xmoc_double;
- else if(!strcmp(static_type, "char*"))
- arg[idx].argType = xmoc_charstar;
- else if(!strcmp(static_type, "TQString"))
- arg[idx].argType = xmoc_TQString;
- XSRETURN_YES;
-
-void
-installsignal(name)
- char *name
- CODE:
- char *file = __FILE__;
- newXS(name, XS_signal, file);
-
-void
-installqt_invoke(name)
- char *name
- CODE:
- char *file = __FILE__;
- newXS(name, XS_qt_invoke, file);
-
-void
-setDebug(on)
- int on
- CODE:
- do_debug = on;
-
-int
-debug()
- CODE:
- RETVAL = do_debug;
- OUTPUT:
- RETVAL
-
-char *
-getTypeNameOfArg(method, idx)
- int method
- int idx
- CODE:
- Smoke::Method &m = qt_Smoke->methods[method];
- Smoke::Index *args = qt_Smoke->argumentList + m.args;
- RETVAL = (char*)qt_Smoke->types[args[idx]].name;
- OUTPUT:
- RETVAL
-
-int
-classIsa(className, base)
- char *className
- char *base
- CODE:
- RETVAL = isDerivedFrom(qt_Smoke, className, base, 0);
- OUTPUT:
- RETVAL
-
-void
-insert_pclassid(p, ix)
- char *p
- int ix
- CODE:
- classcache->insert(p, new Smoke::Index((Smoke::Index)ix));
-
-int
-find_pclassid(p)
- char *p
- CODE:
- Smoke::Index *r = classcache->find(p);
- if(r)
- RETVAL = (int)*r;
- else
- RETVAL = 0;
- OUTPUT:
- RETVAL
-
-void
-insert_mcid(mcid, ix)
- char *mcid
- int ix
- CODE:
- methcache->insert(mcid, new Smoke::Index((Smoke::Index)ix));
-
-int
-find_mcid(mcid)
- char *mcid
- CODE:
- Smoke::Index *r = methcache->find(mcid);
- if(r)
- RETVAL = (int)*r;
- else
- RETVAL = 0;
- OUTPUT:
- RETVAL
-
-char *
-getSVt(sv)
- SV *sv
- CODE:
- RETVAL=get_SVt(sv);
- OUTPUT:
- RETVAL
-
-void *
-make_TQUParameter(name, type, extra, inout)
- char *name
- char *type
- SV *extra
- int inout
- CODE:
- TQUParameter *p = new TQUParameter;
- p->name = new char[strlen(name) + 1];
- strcpy((char*)p->name, name);
- if(!strcmp(type, "bool"))
- p->type = &static_TQUType_bool;
- else if(!strcmp(type, "int"))
- p->type = &static_TQUType_int;
- else if(!strcmp(type, "double"))
- p->type = &static_TQUType_double;
- else if(!strcmp(type, "char*") || !strcmp(type, "const char*"))
- p->type = &static_TQUType_charstar;
- else if(!strcmp(type, "TQString") || !strcmp(type, "TQString&") ||
- !strcmp(type, "const TQString") || !strcmp(type, "const TQString&"))
- p->type = &static_TQUType_TQString;
- else
- p->type = &static_TQUType_ptr;
- // Lacking support for several types. Evil.
- p->inOut = inout;
- p->typeExtra = 0;
- RETVAL = (void*)p;
- OUTPUT:
- RETVAL
-
-void *
-make_TQMetaData(name, method)
- char *name
- void *method
- CODE:
- TQMetaData *m = new TQMetaData; // will be deleted
- m->name = new char[strlen(name) + 1];
- strcpy((char*)m->name, name);
- m->method = (TQUMethod*)method;
- m->access = TQMetaData::Public;
- RETVAL = m;
- OUTPUT:
- RETVAL
-
-void *
-make_TQUMethod(name, params)
- char *name
- SV *params
- CODE:
- TQUMethod *m = new TQUMethod; // permanent memory allocation
- m->name = new char[strlen(name) + 1]; // this too
- strcpy((char*)m->name, name);
- m->count = 0;
- m->parameters = 0;
- if(SvOK(params) && SvRV(params)) {
- AV *av = (AV*)SvRV(params);
- m->count = av_len(av) + 1;
- if(m->count > 0) {
- m->parameters = new TQUParameter[m->count];
- for(int i = 0; i < m->count; i++) {
- SV *sv = av_shift(av);
- if(!SvOK(sv))
- croak("Invalid paramater for TQUMethod\n");
- TQUParameter *p = (TQUParameter*)SvIV(sv);
- SvREFCNT_dec(sv);
- ((TQUParameter*)m->parameters)[i] = *p;
- delete p;
- }
- } else
- m->count = 0;
- }
- RETVAL = m;
- OUTPUT:
- RETVAL
-
-void *
-make_TQMetaData_tbl(list)
- SV *list
- CODE:
- RETVAL = 0;
- if(SvOK(list) && SvRV(list)) {
- AV *av = (AV*)SvRV(list);
- int count = av_len(av) + 1;
- TQMetaData *m = new TQMetaData[count];
- for(int i = 0; i < count; i++) {
- SV *sv = av_shift(av);
- if(!SvOK(sv))
- croak("Invalid metadata\n");
- TQMetaData *old = (TQMetaData*)SvIV(sv);
- SvREFCNT_dec(sv);
- m[i] = *old;
- delete old;
- }
- RETVAL = (void*)m;
- }
- OUTPUT:
- RETVAL
-
-SV *
-make_metaObject(className, parent, slot_tbl, slot_count, signal_tbl, signal_count)
- char *className
- SV *parent
- void *slot_tbl
- int slot_count
- void *signal_tbl
- int signal_count
- CODE:
- smokeperl_object *po = sv_obj_info(parent);
- if(!po || !po->ptr) croak("Cannot create metaObject\n");
- TQMetaObject *meta = TQMetaObject::new_metaobject(
- className, (TQMetaObject*)po->ptr,
- (const TQMetaData*)slot_tbl, slot_count, // slots
- (const TQMetaData*)signal_tbl, signal_count, // signals
- 0, 0, // properties
- 0, 0, // enums
- 0, 0);
-
- // this object-creation code is so, so wrong here
- HV *hv = newHV();
- SV *obj = newRV_noinc((SV*)hv);
-
- smokeperl_object o;
- o.smoke = qt_Smoke;
- o.classId = qt_Smoke->idClass("TQMetaObject");
- o.ptr = meta;
- o.allocated = true;
- sv_magic((SV*)hv, sv_qapp, '~', (char*)&o, sizeof(o));
- MAGIC *mg = mg_find((SV*)hv, '~');
- mg->mg_virtual = &vtbl_smoke;
- char *buf = qt_Smoke->binding->className(o.classId);
- sv_bless(obj, gv_stashpv(buf, TRUE));
- delete[] buf;
- RETVAL = obj;
- OUTPUT:
- RETVAL
-
-void
-dumpObjects()
- CODE:
- hv_iterinit(pointer_map);
- HE *e;
- while(e = hv_iternext(pointer_map)) {
- STRLEN len;
- SV *sv = HeVAL(e);
- printf("key = %s, refcnt = %d, weak = %d, ref? %d\n", HePV(e, len), SvREFCNT(sv), SvWEAKREF(sv), SvROK(sv)?1:0);
- if(SvRV(sv))
- printf("REFCNT = %d\n", SvREFCNT(SvRV(sv)));
- //SvREFCNT_dec(HeVAL(e));
- //HeVAL(e) = &PL_sv_undef;
- }
-
-void
-dangle(obj)
- SV *obj
- CODE:
- if(SvRV(obj))
- SvREFCNT_inc(SvRV(obj));
-
-void
-setAllocated(obj, b)
- SV *obj
- bool b
- CODE:
- smokeperl_object *o = sv_obj_info(obj);
- if(o) {
- o->allocated = b;
- }
-
-void
-setqapp(obj)
- SV *obj
- CODE:
- if(!obj || !SvROK(obj))
- croak("Invalid TQt::Application object. Couldn't set TQt::app()\n");
- sv_qapp = SvRV(obj);
-
-void
-setThis(obj)
- SV *obj
- CODE:
- sv_setsv_mg(sv_this, obj);
-
-void
-deleteObject(obj)
- SV *obj
- CODE:
- smokeperl_object *o = sv_obj_info(obj);
- if(!o) { XSRETURN_EMPTY; }
- TQObject *qobj = (TQObject*)o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQObject"));
- delete qobj;
-
-void
-mapObject(obj)
- SV *obj
- CODE:
- smokeperl_object *o = sv_obj_info(obj);
- if(!o)
- XSRETURN_EMPTY;
- SmokeClass c( o->smoke, o->classId );
- if(!c.hasVirtual() ) {
- XSRETURN_EMPTY;
- }
- mapPointer(obj, o, pointer_map, o->classId, 0);
-
-bool
-isTQObject(obj)
- SV *obj
- CODE:
- RETVAL = 0;
- smokeperl_object *o = sv_obj_info(obj);
- if(o && isTQObject(o->smoke, o->classId))
- RETVAL = 1;
- OUTPUT:
- RETVAL
-
-bool
-isValidAllocatedPointer(obj)
- SV *obj
- CODE:
- RETVAL = 0;
- smokeperl_object *o = sv_obj_info(obj);
- if(o && o->ptr && o->allocated)
- RETVAL = 1;
- OUTPUT:
- RETVAL
-
-SV*
-findAllocatedObjectFor(obj)
- SV *obj
- CODE:
- RETVAL = &PL_sv_undef;
- smokeperl_object *o = sv_obj_info(obj);
- SV *ret;
- if(o && o->ptr && (ret = getPointerObject(o->ptr)))
- RETVAL = ret;
- OUTPUT:
- RETVAL
-
-SV *
-getGV(cv)
- SV *cv
- CODE:
- RETVAL = (SvROK(cv) && (SvTYPE(SvRV(cv))==SVt_PVCV) ?
- SvREFCNT_inc(CvGV((CV*)SvRV(cv))) : &PL_sv_undef);
- OUTPUT:
- RETVAL
-
-int
-idClass(name)
- char *name
- CODE:
- RETVAL = qt_Smoke->idClass(name);
- OUTPUT:
- RETVAL
-
-int
-idMethodName(name)
- char *name
- CODE:
- RETVAL = qt_Smoke->idMethodName(name);
- OUTPUT:
- RETVAL
-
-int
-idMethod(idclass, idmethodname)
- int idclass
- int idmethodname
- CODE:
- RETVAL = qt_Smoke->idMethod(idclass, idmethodname);
- OUTPUT:
- RETVAL
-
-void
-findMethod(c, name)
- char *c
- char *name
- PPCODE:
- Smoke::Index meth = qt_Smoke->findMethod(c, name);
-// printf("DAMNIT on %s::%s => %d\n", c, name, meth);
- if(!meth) {
- // empty list
- } else if(meth > 0) {
- Smoke::Index i = qt_Smoke->methodMaps[meth].method;
- if(!i) { // shouldn't happen
- croak("Corrupt method %s::%s", c, name);
- } else if(i > 0) { // single match
- PUSHs(sv_2mortal(newSViv(
- (IV)qt_Smoke->methodMaps[meth].method
- )));
- } else { // multiple match
- i = -i; // turn into ambiguousMethodList index
- while(qt_Smoke->ambiguousMethodList[i]) {
- PUSHs(sv_2mortal(newSViv(
- (IV)qt_Smoke->ambiguousMethodList[i]
- )));
- i++;
- }
- }
- }
-
-void
-findMethodFromIds(idclass, idmethodname)
- int idclass
- int idmethodname
- PPCODE:
- Smoke::Index meth = qt_Smoke->findMethod(idclass, idmethodname);
- if(!meth) {
- // empty list
- } else if(meth > 0) {
- Smoke::Index i = qt_Smoke->methodMaps[meth].method;
- if(i >= 0) { // single match
- PUSHs(sv_2mortal(newSViv((IV)i)));
- } else { // multiple match
- i = -i; // turn into ambiguousMethodList index
- while(qt_Smoke->ambiguousMethodList[i]) {
- PUSHs(sv_2mortal(newSViv(
- (IV)qt_Smoke->ambiguousMethodList[i]
- )));
- i++;
- }
- }
- }
-
-# findAllMethods(classid [, startingWith]) : returns { "mungedName" => [index in methods, ...], ... }
-
-HV*
-findAllMethods(classid, ...)
- SV* classid
- CODE:
- RETVAL=newHV();
- if(SvIOK(classid)) {
- Smoke::Index c = (Smoke::Index) SvIV(classid);
- char * pat = 0L;
- if(items > 1 && SvPOK(ST(1)))
- pat = SvPV_nolen(ST(1));
- Smoke::Index imax = qt_Smoke->numMethodMaps;
- Smoke::Index imin = 0, icur = -1, methmin = 0, methmax = 0;
- int icmp = -1;
- while(imax >= imin) {
- icur = (imin + imax) / 2;
- icmp = qt_Smoke->leg(qt_Smoke->methodMaps[icur].classId, c);
- if(!icmp) {
- Smoke::Index pos = icur;
- while(icur && qt_Smoke->methodMaps[icur-1].classId == c)
- icur --;
- methmin = icur;
- icur = pos;
- while(icur < imax && qt_Smoke->methodMaps[icur+1].classId == c)
- icur ++;
- methmax = icur;
- break;
- }
- if (icmp > 0)
- imax = icur - 1;
- else
- imin = icur + 1;
- }
- if(!icmp) {
- for(Smoke::Index i=methmin ; i <= methmax ; i++) {
- Smoke::Index m = qt_Smoke->methodMaps[i].name;
- if(!pat || !strncmp(qt_Smoke->methodNames[m], pat, strlen(pat))) {
- Smoke::Index ix= qt_Smoke->methodMaps[i].method;
- AV* meths = newAV();
- if(ix >= 0) { // single match
- av_push(meths, newSViv((IV)ix));
- } else { // multiple match
- ix = -ix; // turn into ambiguousMethodList index
- while(qt_Smoke->ambiguousMethodList[ix]) {
- av_push(meths, newSViv((IV)qt_Smoke->ambiguousMethodList[ix]));
- ix++;
- }
- }
- hv_store(RETVAL, qt_Smoke->methodNames[m],strlen(qt_Smoke->methodNames[m]),newRV_inc((SV*)meths),0);
- }
- }
- }
- }
- OUTPUT:
- RETVAL
-
-SV *
-dumpCandidates(rmeths)
- SV *rmeths
- CODE:
- if(SvROK(rmeths) && SvTYPE(SvRV(rmeths)) == SVt_PVAV) {
- AV *methods = (AV*)SvRV(rmeths);
- SV *errmsg = newSVpvf("");
- for(int i = 0; i <= av_len(methods); i++) {
- sv_catpv(errmsg, "\t");
- IV id = SvIV(*(av_fetch(methods, i, 0)));
- Smoke::Method &meth = qt_Smoke->methods[id];
- const char *tname = qt_Smoke->types[meth.ret].name;
- if(meth.flags & Smoke::mf_static) sv_catpv(errmsg, "static ");
- sv_catpvf(errmsg, "%s ", (tname ? tname:"void"));
- sv_catpvf(errmsg, "%s::%s(", qt_Smoke->classes[meth.classId].className, qt_Smoke->methodNames[meth.name]);
- for(int i = 0; i < meth.numArgs; i++) {
- if(i) sv_catpv(errmsg, ", ");
- tname = qt_Smoke->types[qt_Smoke->argumentList[meth.args+i]].name;
- sv_catpv(errmsg, (tname ? tname:"void"));
- }
- sv_catpv(errmsg, ")");
- if(meth.flags & Smoke::mf_const) sv_catpv(errmsg, " const");
- sv_catpv(errmsg, "\n");
- }
- RETVAL=errmsg;
- }
- else
- RETVAL=newSVpvf("");
- OUTPUT:
- RETVAL
-
-SV *
-catArguments(r_args)
- SV* r_args
- CODE:
- RETVAL=newSVpvf("");
- if(SvROK(r_args) && SvTYPE(SvRV(r_args)) == SVt_PVAV) {
- AV* args=(AV*)SvRV(r_args);
- for(int i = 0; i <= av_len(args); i++) {
- SV **arg=av_fetch(args, i, 0);
- if(i) sv_catpv(RETVAL, ", ");
- if(!arg || !SvOK(*arg)) {
- sv_catpv(RETVAL, "undef");
- } else if(SvROK(*arg)) {
- smokeperl_object *o = sv_obj_info(*arg);
- if(o)
- sv_catpv(RETVAL, o->smoke->className(o->classId));
- else
- sv_catsv(RETVAL, *arg);
- } else {
- bool isString = SvPOK(*arg);
- STRLEN len;
- char *s = SvPV(*arg, len);
- if(isString) sv_catpv(RETVAL, "'");
- sv_catpvn(RETVAL, s, len > 10 ? 10 : len);
- if(len > 10) sv_catpv(RETVAL, "...");
- if(isString) sv_catpv(RETVAL, "'");
- }
- }
- }
- OUTPUT:
- RETVAL
-
-SV *
-callMethod(...)
- PPCODE:
- if(_current_method) {
- MethodCall c(qt_Smoke, _current_method, &ST(0), items);
- c.next();
- SV *ret = c.var();
- SvREFCNT_inc(ret);
- PUSHs(sv_2mortal(ret));
- } else
- PUSHs(sv_newmortal());
-
-bool
-isObject(obj)
- SV *obj
- CODE:
- RETVAL = sv_to_ptr(obj) ? TRUE : FALSE;
- OUTPUT:
- RETVAL
-
-void
-setCurrentMethod(meth)
- int meth
- CODE:
- // FIXME: damn, this is lame, and it doesn't handle ambiguous methods
- _current_method = meth; //qt_Smoke->methodMaps[meth].method;
-
-SV *
-getClassList()
- CODE:
- AV *av = newAV();
- for(int i = 1; i <= qt_Smoke->numClasses; i++) {
-//printf("%s => %d\n", qt_Smoke->classes[i].className, i);
- av_push(av, newSVpv(qt_Smoke->classes[i].className, 0));
-// hv_store(hv, qt_Smoke->classes[i].className, 0, newSViv(i), 0);
- }
- RETVAL = newRV((SV*)av);
- OUTPUT:
- RETVAL
-
-void
-installthis(package)
- char *package
- CODE:
- if(!package) XSRETURN_EMPTY;
- char *name = new char[strlen(package) + 7];
- char *file = __FILE__;
- strcpy(name, package);
- strcat(name, "::this");
- // *{ $name } = sub () : lvalue;
- CV *thissub = newXS(name, XS_this, file);
- sv_setpv((SV*)thissub, ""); // sub this () : lvalue;
- delete[] name;
-
-void
-installattribute(package, name)
- char *package
- char *name
- CODE:
- if(!package || !name) XSRETURN_EMPTY;
- char *attr = new char[strlen(package) + strlen(name) + 3];
- sprintf(attr, "%s::%s", package, name);
- char *file = __FILE__;
- // *{ $attr } = sub () : lvalue;
- CV *attrsub = newXS(attr, XS_attr, file);
- sv_setpv((SV*)attrsub, "");
- CvLVALUE_on(attrsub);
- CvNODEBUG_on(attrsub);
- delete[] attr;
-
-void
-installsuper(package)
- char *package
- CODE:
- if(!package) XSRETURN_EMPTY;
- char *attr = new char[strlen(package) + 8];
- sprintf(attr, "%s::SUPER", package);
- char *file = __FILE__;
- CV *attrsub = newXS(attr, XS_super, file);
- sv_setpv((SV*)attrsub, "");
- delete[] attr;
-
-void
-installautoload(package)
- char *package
- CODE:
- if(!package) XSRETURN_EMPTY;
- char *autoload = new char[strlen(package) + 11];
- strcpy(autoload, package);
- strcat(autoload, "::_UTOLOAD");
- char *file = __FILE__;
- // *{ $package."::AUTOLOAD" } = XS_AUTOLOAD
- newXS(autoload, XS_AUTOLOAD, file);
- delete[] autoload;
-
-# ----------------- XSUBS for TQt:: -----------------
-
-MODULE = TQt PACKAGE = TQt
-
-SV *
-this()
- CODE:
- RETVAL = newSVsv(sv_this);
- OUTPUT:
- RETVAL
-
-SV *
-app()
- CODE:
- RETVAL = newRV_inc(sv_qapp);
- OUTPUT:
- RETVAL
-
-SV *
-version()
- CODE:
- RETVAL = newSVpv(TQT_VERSION_STR,0);
- OUTPUT:
- RETVAL
-
-BOOT:
- init_qt_Smoke();
- qt_Smoke->binding = new TQtSmokeBinding(qt_Smoke);
- install_handlers(TQt_handlers);
- pointer_map = newHV();
- sv_this = newSV(0);
- methcache = new TQAsciiDict<Smoke::Index>(1187);
- classcache = new TQAsciiDict<Smoke::Index>(827);
- methcache->setAutoDelete(1);
- classcache->setAutoDelete(1);