diff options
Diffstat (limited to 'Modules/objc.c')
-rw-r--r-- | Modules/objc.c | 651 |
1 files changed, 0 insertions, 651 deletions
diff --git a/Modules/objc.c b/Modules/objc.c deleted file mode 100644 index 9e70912712..0000000000 --- a/Modules/objc.c +++ /dev/null @@ -1,651 +0,0 @@ -/*********************************************************** -Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, -The Netherlands. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -******************************************************************/ - -/* Objective-C interface for NeXTStep */ -/* Tested with NeXTStep 3.3 on Intel and Sparc architectures */ - -/* Original author: Jon M. Kutemeier */ -/* Revamped and maintained by: Guido van Rossum */ - -/* XXX To do: - - bug??? x.send('name', []) gives weird error - - rename functions from objc_* to ObjC_* - - change send(sel, [a, b, c]) to send(self, a, b, c) - - call back to Python from Objective-C - */ - -/* Python header file */ -#include "Python.h" - -/* NeXT headers */ -#include <sys/param.h> -#include <mach-o/rld.h> -#include <objc/objc.h> -#include <objc/objc-runtime.h> -#import <remote/NXProxy.h> - -/* Distinguish between ObjC classes and instances */ -typedef enum { - OBJC_CLASS, - OBJC_INSTANCE, -} ObjC_Typecode; - -/* Exception raised for ObjC specific errors */ -static PyObject *ObjC_Error; - -/* Python wrapper about ObjC id (instance or class) */ -typedef struct { - PyObject_HEAD - id obj; - ObjC_Typecode type; - int owned; -} ObjCObject; - -/* Corresponding Python type object */ -staticforward PyTypeObject ObjC_Type; - -/* Corresponding Python type check macro */ -#define ObjC_Check(o) ((o)->ob_type == &ObjC_Type) - -/* Create a new ObjCObject */ -static ObjCObject * -newObjCObject(obj, type, owned) - id obj; - ObjC_Typecode type; - int owned; -{ - ObjCObject *self; - - self = PyObject_NEW(ObjCObject, &ObjC_Type); - if (self == NULL) - return NULL; - - self->obj = obj; - self->type = type; - self->owned = owned; - - return self; -} - -static void -objc_sendfree(self) - ObjCObject *self; -{ - if (self->obj) - self->obj = (id)objc_msgSend(self->obj, SELUID("free")); -} - -/* Deallocate an ObjCObject */ -static void -objc_dealloc(self) - ObjCObject *self; -{ - if (self->owned) - objc_sendfree(self); - PyMem_DEL(self); -} - -/* Return a string representation of an ObjCObject */ -static PyObject * -objc_repr(self) - ObjCObject *self; -{ - char buffer[512]; - char *p = buffer; - if (self->obj == nil) - p = "<Objective-C nil>"; - else { - char *t; - switch (self->type) { - case OBJC_CLASS: t = "class"; break; - case OBJC_INSTANCE: t = "instance"; break; - default: t = "???"; break; - } - sprintf(buffer, "<Objective-C %s %s at %lx>", - NAMEOF(self->obj), t, (long)(self->obj)); - } - return PyString_FromString(p); -} - -/*** ObjCObject methods ***/ - -/* Call an object's free method */ -static PyObject * -objc_free(self, args) - ObjCObject *self; - PyObject *args; -{ - if (!PyArg_ParseTuple(args, "")) - return NULL; - objc_sendfree(self); -} - -/* Send a message to an ObjCObject. - The Python call looks like e.g. obj.send('moveTo::', [arg1, arg2]) - which translates into Objective-C as [obj moveTo: arg1 : arg2] */ -static PyObject * -objc_send(self, args) - ObjCObject *self; - PyObject *args; -{ - char *methodname; - char *margBuff = NULL; - PyObject *retobject = NULL; - PyObject *arglist; - id receiver, obj; - char *type; - SEL sel; - Method meth; - unsigned int margCount, margSize; - int offset, i; - - if (!PyArg_ParseTuple(args, "sO!", &methodname, &PyList_Type, &arglist)) - return NULL; - - /* Get the method descriptor from the object */ - - receiver = self->obj; - sel = SELUID(methodname); - - switch(self->type) { - case OBJC_CLASS: - meth = class_getClassMethod(receiver->isa, sel); - break; - case OBJC_INSTANCE: - meth = class_getInstanceMethod(receiver->isa, sel); - break; - default: - PyErr_SetString(ObjC_Error, - "receiver's type is neither instance not class!?!?"); - return NULL; - } - - if (!meth) { - PyErr_SetString(ObjC_Error, "receiver has no method by that name"); - return NULL; - } - - /* Fill in the argument list, type-checking the arguments */ - - margCount = method_getNumberOfArguments(meth); - - if (PyList_Size(arglist) + 2 != margCount) { - PyErr_SetString(ObjC_Error, - "wrong number of arguments for this method"); - return NULL; - } - - margSize = method_getSizeOfArguments(meth); - margBuff = PyMem_NEW(char, margSize+1); - if (margBuff == NULL) - return PyErr_NoMemory(); - - method_getArgumentInfo(meth, 0, &type, &offset); - marg_setValue(margBuff, offset, id, receiver); - - method_getArgumentInfo(meth, 1, &type, &offset); - marg_setValue(margBuff, offset, SEL, sel); - - for (i = 2; i < margCount; i++) { - PyObject *argument; - method_getArgumentInfo(meth, i, &type, &offset); - - argument = PyList_GetItem(arglist, i-2); - - /* scan past protocol-type modifiers */ - while (strchr("rnNoOV", *type) != 0) - type++; - - /* common type checks */ - switch(*type) { - - /* XXX The errors here should point out which argument */ - - case 'c': - case '*': - case 'C': - if (!PyString_Check(argument)) { - PyErr_SetString(ObjC_Error, "string argument expected"); - goto error; - } - break; - - case 'i': - case 's': - case 'I': - case 'S': - case 'l': - case 'L': - case '^': - if (!PyInt_Check(argument)) { - PyErr_SetString(ObjC_Error, "integer argument expected"); - goto error; - } - break; - - case 'f': - case 'd': - if (!PyFloat_Check(argument)) { - PyErr_SetString(ObjC_Error, "float argument expected"); - goto error; - } - break; - - } - - /* convert and store the argument */ - switch (*type) { - - case 'c': /* char */ - marg_setValue(margBuff, offset, char, - PyString_AsString(argument)[0]); - break; - - case 'C': /* unsigned char */ - marg_setValue(margBuff, offset, unsigned char, - PyString_AsString(argument)[0]); - break; - - case '*': /* string */ - marg_setValue(margBuff, offset, char *, - PyString_AsString(argument)); - break; - - case 'i': /* int */ - marg_setValue(margBuff, offset, int, - PyInt_AsLong(argument)); - break; - - case 'I': /* unsigned int */ - marg_setValue(margBuff, offset, unsigned int, - PyInt_AsLong(argument)); - break; - - case 's': /* short */ - marg_setValue(margBuff, offset, short, - PyInt_AsLong(argument)); - break; - - case 'S': /* unsigned short */ - marg_setValue(margBuff, offset, unsigned short, - PyInt_AsLong(argument)); - break; - - case 'l': /* long */ - marg_setValue(margBuff, offset, long, - PyInt_AsLong(argument)); - break; - - case 'L': /* unsigned long */ - marg_setValue(margBuff, offset, unsigned long, - PyInt_AsLong(argument)); - break; - - case 'f': /* float */ - marg_setValue(margBuff, offset, float, - (float)PyFloat_AsDouble(argument)); - break; - - case 'd': /* double */ - marg_setValue(margBuff, offset, double, - PyFloat_AsDouble(argument)); - break; - - case '@': /* id (or None) */ - if (ObjC_Check(argument)) - marg_setValue(margBuff, offset, id, - ((ObjCObject *)(argument))->obj); - else if (argument == Py_None) - marg_setValue(margBuff, offset, id, nil); - else { - PyErr_SetString(ObjC_Error, "id or None argument expected"); - goto error; - } - break; - - case '^': /* void * (use int) */ - marg_setValue(margBuff, offset, void *, - (void *)PyInt_AsLong(argument)); - break; - - case ':': /* SEL (use string or int) */ - if (PyInt_Check(argument)) - marg_setValue(margBuff, offset, SEL, - (SEL)PyInt_AsLong(argument)); - else if (PyString_Check(argument)) - marg_setValue(margBuff, offset, SEL, - SELUID(PyString_AsString(argument))); - else { - PyErr_SetString(ObjC_Error, - "selector string or int argument expected"); - goto error; - } - break; - - case '#': /* Class (may also use int) */ - if (ObjC_Check(argument) && - ((ObjCObject *)argument)->type == OBJC_INSTANCE) - marg_setValue(margBuff, offset, Class *, - (Class *)((ObjCObject *)argument)->obj); - else if (PyInt_Check(argument)) - marg_setValue(margBuff, offset, Class *, - (Class *)PyInt_AsLong(argument)); - else { - PyErr_SetString(ObjC_Error, - "ObjC class object required"); - goto error; - } - break; - - default: - PyErr_SetString(ObjC_Error, "unknown argument type"); - goto error; - - } - } - - /* Call the method and set the return value */ - - type = meth->method_types; - - while (strchr("rnNoOV", *type)) - type++; - - switch(*type) { - -/* Cast objc_msgSendv to a function returning the right thing */ -#define MS_CAST(type) ((type (*)())objc_msgSendv) - - case 'c': - case '*': - case 'C': - retobject = (PyObject *)PyString_FromString( - MS_CAST(char *)(receiver, sel, margSize, margBuff)); - break; - - case 'i': - case 's': - case 'I': - case 'S': - retobject = (PyObject *)PyInt_FromLong( - MS_CAST(int)(receiver, sel, margSize, margBuff)); - break; - - case 'l': - case 'L': - case '^': - retobject = (PyObject *)PyInt_FromLong( - MS_CAST(long)(receiver, sel, margSize, margBuff)); - break; - - case 'f': - retobject = (PyObject *)PyFloat_FromDouble( - MS_CAST(float)(receiver, sel, margSize, margBuff)); - break; - - case 'd': - retobject = (PyObject *)PyFloat_FromDouble( - MS_CAST(double)(receiver, sel, margSize, margBuff)); - break; - - case '@': - obj = MS_CAST(id)(receiver, sel, margSize, margBuff); - if (obj == nil) { - retobject = Py_None; - Py_INCREF(retobject); - } - else if (obj != receiver) - retobject = (PyObject *)newObjCObject(obj, OBJC_INSTANCE, 0); - else { - retobject = (PyObject *)self; - Py_INCREF(retobject); - } - break; - - case ':': - retobject = (PyObject *)PyInt_FromLong( - (long)MS_CAST(SEL)(receiver, sel, margSize, margBuff)); - break; - - case '#': - retobject = (PyObject *)PyInt_FromLong( - (long)MS_CAST(Class *)(receiver, sel, margSize, margBuff)); - break; - -#undef MS_CAST - - } - - error: - PyMem_XDEL(margBuff); - return retobject; -} - -/* List of methods for ObjCObject */ -static PyMethodDef objc_methods[] = { - {"send", (PyCFunction)objc_send, 1}, - {"free", (PyCFunction)objc_free, 1}, - {NULL, NULL} /* sentinel */ -}; - -/* Get an attribute of an ObjCObject */ -static PyObject * -objc_getattr(self, name) - ObjCObject *self; - char *name; -{ - PyObject *method; - - /* Try a function method */ - method = Py_FindMethod(objc_methods, (PyObject *)self, name); - if (method != NULL) - return method; - PyErr_Clear(); - - /* Try an instance variable */ - if (strcmp(name, "obj") == 0) - return PyInt_FromLong((long)self->obj); - if (strcmp(name, "type") == 0) - return PyInt_FromLong((long)self->type); - if (strcmp(name, "owned") == 0) - return PyInt_FromLong((long)self->owned); - if (strcmp(name, "name") == 0) - return PyString_FromString(NAMEOF(self->obj)); - if (strcmp(name, "__members__") == 0) - return Py_BuildValue("[sss]", "name", "obj", "owned", "type"); - - PyErr_SetString(PyExc_AttributeError, name); - return NULL; -} - -/* The type object */ -static PyTypeObject ObjC_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size*/ - "objc", /*tp_name*/ - sizeof(ObjCObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)objc_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)objc_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)objc_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, 0, 0, 0, /*xxx1-4*/ - "Objective-C id wrapper", /*tp_doc*/ -}; - - - -/*** Top-level functions ***/ - -/* Max #files passed to loadobjectfile() */ -#define MAXRLD 128 - -/* Load a list of object files */ -static PyObject * -objc_loadobjectfiles(self, args) -PyObject *self; /* Not used */ -PyObject *args; -{ - NXStream *errorStream; - struct mach_header *new_header; - const char *filenames[MAXRLD+1]; - long ret; - char *streamBuf; - PyObject *filelist, *file; - int listsize, len, maxLen, i; - - if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &filelist)) - return NULL; - - listsize = PyList_Size(filelist); - - if (listsize > MAXRLD) { - PyErr_SetString(ObjC_Error, "more than 128 files in list"); - return NULL; - } - - errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); - - for (i = 0; i < listsize; i++) { - file = PyList_GetItem(filelist, i); - - if (!PyString_Check(file)) - { - PyErr_SetString(ObjC_Error, - "all list items must be strings"); - return NULL; - } - - filenames[i] = PyString_AsString(file); - } - - filenames[listsize] = NULL; - - ret = objc_loadModules(filenames, errorStream, NULL, &new_header, NULL); - - /* extract the error messages for the exception */ - - if(ret) { - NXPutc(errorStream, (char)0); - - NXGetMemoryBuffer(errorStream, &streamBuf, &len, &maxLen); - PyErr_SetString(ObjC_Error, streamBuf); - } - - NXCloseMemory(errorStream, NX_FREEBUFFER); - - if(ret) - return NULL; - - Py_XINCREF(Py_None); - return Py_None; -} - -static PyObject * -objc_lookupclass(self, args) -PyObject *self; /* Not used */ -PyObject *args; -{ - char *classname; - id class; - - if (!PyArg_ParseTuple(args, "s", &classname)) - return NULL; - - if (!(class = objc_lookUpClass(classname))) - { - PyErr_SetString(ObjC_Error, "unknown ObjC class"); - return NULL; - } - - return (PyObject *)newObjCObject(class, OBJC_CLASS, 0); -} - -/* List all classes */ -static PyObject * -objc_listclasses(self, args) - ObjCObject *self; - PyObject *args; -{ - NXHashTable *class_hash = objc_getClasses(); - NXHashState state = NXInitHashState(class_hash); - Class classid; - PyObject *list; - - if (!PyArg_ParseTuple(args, "")) - return NULL; - - list = PyList_New(0); - if (list == NULL) - return NULL; - - while (NXNextHashState(class_hash, &state, (void**)&classid)) { - ObjCObject *item = newObjCObject(classid, OBJC_CLASS, 0); - if (item == NULL || PyList_Append(list, (PyObject *)item) < 0) { - Py_XDECREF(item); - Py_DECREF(list); - return NULL; - } - Py_INCREF(item); - } - - return list; -} - -/* List of top-level functions */ -static PyMethodDef objc_class_methods[] = { - {"loadobjectfiles", objc_loadobjectfiles, 1}, - {"lookupclass", objc_lookupclass, 1}, - {"listclasses", objc_listclasses, 1}, - {NULL, NULL} /* sentinel */ -}; - -/* Initialize for the module */ -void -initobjc() -{ - PyObject *m, *d; - - m = Py_InitModule("objc", objc_class_methods); - d = PyModule_GetDict(m); - - ObjC_Error = PyString_FromString("objc.error"); - PyDict_SetItemString(d, "error", ObjC_Error); - - if (PyErr_Occurred()) - Py_FatalError("can't initialize module objc"); - -#ifdef WITH_THREAD - objc_setMultithreaded(1); -#endif -} |