summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/getpath.c41
-rw-r--r--Modules/main.c246
-rw-r--r--Modules/objc.c651
3 files changed, 938 insertions, 0 deletions
diff --git a/Modules/getpath.c b/Modules/getpath.c
new file mode 100644
index 0000000..8e1c00d
--- /dev/null
+++ b/Modules/getpath.c
@@ -0,0 +1,41 @@
+#include "Python.h"
+#include "osdefs.h"
+
+
+#ifndef PYTHONPATH
+#define PYTHONPATH ".:/usr/local/lib/python"
+#endif
+
+
+/* Return the initial python search path. This is called once from
+ initsys() to initialize sys.path. The environment variable
+ PYTHONPATH is fetched and the default path appended. The default
+ path may be passed to the preprocessor; if not, a system-dependent
+ default is used. */
+
+char *
+getpythonpath()
+{
+ char *path = getenv("PYTHONPATH");
+ char *defpath = PYTHONPATH;
+ static char *buf = NULL;
+ char *p;
+ int n;
+
+ if (path == NULL)
+ path = "";
+ n = strlen(path) + strlen(defpath) + 2;
+ if (buf != NULL) {
+ free(buf);
+ buf = NULL;
+ }
+ buf = malloc(n);
+ if (buf == NULL)
+ Py_FatalError("not enough memory to copy module search path");
+ strcpy(buf, path);
+ p = buf + strlen(buf);
+ if (p != buf)
+ *p++ = DELIM;
+ strcpy(p, defpath);
+ return buf;
+}
diff --git a/Modules/main.c b/Modules/main.c
new file mode 100644
index 0000000..4763a59
--- /dev/null
+++ b/Modules/main.c
@@ -0,0 +1,246 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+/* Python interpreter main program */
+
+#include "Python.h"
+
+
+/* Interface to getopt(): */
+extern int optind;
+extern char *optarg;
+extern int getopt(); /* PROTO((int, char **, char *)); -- not standardized */
+
+
+extern int Py_DebugFlag; /* For parser.c, declared in pythonrun.c */
+extern int Py_VerboseFlag; /* For import.c, declared in pythonrun.c */
+extern int Py_SuppressPrintingFlag; /* For ceval.c, declared in pythonrun.c */
+
+
+/* Subroutines that live in their own file */
+extern char *getversion();
+extern char *getcopyright();
+
+
+/* For getprogramname(); set by main() */
+static char *argv0;
+
+/* For getargcargv(); set by main() */
+static char **orig_argv;
+static int orig_argc;
+
+
+/* Short usage message (with %s for argv0) */
+static char *usage_line =
+"usage: %s [-d] [-i] [-s] [-u ] [-v] [-c cmd | file | -] [arg] ...\n";
+
+/* Long usage message, split into parts < 512 bytes */
+static char *usage_top = "\n\
+Options and arguments (and corresponding environment variables):\n\
+-d : debug output from parser (also PYTHONDEBUG=x)\n\
+-i : inspect interactively after running script (also PYTHONINSPECT=x)\n\
+-s : suppress printing of top level expressions (also PYTHONSUPPRESS=x)\n\
+-u : unbuffered stdout and stderr (also PYTHONUNBUFFERED=x)\n\
+-v : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
+-c cmd : program passed in as string (terminates option list)\n\
+";
+static char *usage_bot = "\
+file : program read from script file\n\
+- : program read from stdin (default; interactive mode if a tty)\n\
+arg ...: arguments passed to program in sys.argv[1:]\n\
+\n\
+Other environment variables:\n\
+PYTHONSTARTUP: file executed on interactive startup (no default)\n\
+PYTHONPATH : colon-separated list of directories prefixed to the\n\
+ default module search path. The result is sys.path.\n\
+";
+
+
+/* Main program */
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int sts;
+ char *command = NULL;
+ char *filename = NULL;
+ FILE *fp = stdin;
+ char *p;
+ int inspect = 0;
+ int unbuffered = 0;
+
+ orig_argc = argc; /* For getargcargv() */
+ orig_argv = argv;
+ argv0 = argv[0]; /* For getprogramname() */
+
+ if ((p = getenv("PYTHONDEBUG")) && *p != '\0')
+ Py_DebugFlag = 1;
+ if ((p = getenv("PYTHONSUPPRESS")) && *p != '\0')
+ Py_SuppressPrintingFlag = 1;
+ if ((p = getenv("PYTHONVERBOSE")) && *p != '\0')
+ Py_VerboseFlag = 1;
+ if ((p = getenv("PYTHONINSPECT")) && *p != '\0')
+ inspect = 1;
+ if ((p = getenv("PYTHONUNBUFFERED")) && *p != '\0')
+ unbuffered = 1;
+
+ while ((c = getopt(argc, argv, "c:disuv")) != EOF) {
+ if (c == 'c') {
+ /* -c is the last option; following arguments
+ that look like options are left for the
+ the command to interpret. */
+ command = malloc(strlen(optarg) + 2);
+ if (command == NULL)
+ Py_FatalError(
+ "not enough memory to copy -c argument");
+ strcpy(command, optarg);
+ strcat(command, "\n");
+ break;
+ }
+
+ switch (c) {
+
+ case 'd':
+ Py_DebugFlag++;
+ break;
+
+ case 'i':
+ inspect++;
+ break;
+
+ case 's':
+ Py_SuppressPrintingFlag++;
+ break;
+
+ case 'u':
+ unbuffered++;
+ break;
+
+ case 'v':
+ Py_VerboseFlag++;
+ break;
+
+ /* This space reserved for other options */
+
+ default:
+ fprintf(stderr, usage_line, argv[0]);
+ fprintf(stderr, usage_top);
+ fprintf(stderr, usage_bot);
+ exit(2);
+ /*NOTREACHED*/
+
+ }
+ }
+
+ if (unbuffered) {
+#ifndef MPW
+ setbuf(stdout, (char *)NULL);
+ setbuf(stderr, (char *)NULL);
+#else
+ /* On MPW (3.2) unbuffered seems to hang */
+ setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
+ setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
+#endif
+ }
+
+ if (command == NULL && optind < argc &&
+ strcmp(argv[optind], "-") != 0)
+ filename = argv[optind];
+
+ if (Py_VerboseFlag ||
+ command == NULL && filename == NULL && isatty((int)fileno(fp)))
+ fprintf(stderr, "Python %s\n%s\n",
+ getversion(), getcopyright());
+
+ if (filename != NULL) {
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "%s: can't open file '%s'\n",
+ argv[0], filename);
+ exit(2);
+ }
+ }
+
+ Py_Initialize();
+
+ if (command != NULL) {
+ /* Backup optind and force sys.argv[0] = '-c' */
+ optind--;
+ argv[optind] = "-c";
+ }
+
+ PySys_SetArgv(argc-optind, argv+optind);
+
+ if (command) {
+ sts = PyRun_SimpleString(command) != 0;
+ }
+ else {
+ if (filename == NULL && isatty((int)fileno(fp))) {
+ char *startup = getenv("PYTHONSTARTUP");
+ if (startup != NULL && startup[0] != '\0') {
+ FILE *fp = fopen(startup, "r");
+ if (fp != NULL) {
+ (void) PyRun_SimpleFile(fp, startup);
+ PyErr_Clear();
+ fclose(fp);
+ }
+ }
+ }
+ sts = PyRun_AnyFile(
+ fp, filename == NULL ? "<stdin>" : filename) != 0;
+ if (filename != NULL)
+ fclose(fp);
+ }
+
+ if (inspect && isatty((int)fileno(stdin)) &&
+ (filename != NULL || command != NULL))
+ sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
+
+ Py_Exit(sts);
+ /*NOTREACHED*/
+}
+
+
+/* Return the program name -- some code out there needs this. */
+
+char *
+getprogramname()
+{
+ return argv0;
+}
+
+
+/* Make the *original* argc/argv available to other modules.
+ This is rare, but it is needed by the secureware extension. */
+
+void
+getargcargv(argc,argv)
+ int *argc;
+ char ***argv;
+{
+ *argc = orig_argc;
+ *argv = orig_argv;
+}
diff --git a/Modules/objc.c b/Modules/objc.c
new file mode 100644
index 0000000..9e70912
--- /dev/null
+++ b/Modules/objc.c
@@ -0,0 +1,651 @@
+/***********************************************************
+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
+}