| /*********************************************************** |
| 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 or Corporation for National Research Initiatives or |
| CNRI not be used in advertising or publicity pertaining to |
| distribution of the software without specific, written prior |
| permission. |
| |
| While CWI is the initial source for this software, a modified version |
| is made available by the Corporation for National Research Initiatives |
| (CNRI) at the Internet address ftp://ftp.python.org. |
| |
| STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH |
| REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF |
| MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH |
| CENTRUM OR CNRI 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. |
| |
| ******************************************************************/ |
| |
| /* Sanity check */ |
| #ifndef __powerc |
| #error Please port this code to your architecture first... |
| #endif |
| |
| /* |
| ** Define to include testroutines (at the end) |
| */ |
| #define TESTSUPPORT |
| |
| #include "Python.h" |
| #include "macglue.h" |
| #include "macdefs.h" |
| #include <CodeFragments.h> |
| |
| /* Prototypes for routines not in any include file (shame, shame) */ |
| extern PyObject *ResObj_New(Handle); |
| extern int ResObj_Convert(PyObject *, Handle *); |
| |
| static PyObject *ErrorObject; |
| |
| /* Debugging macro */ |
| #ifdef TESTSUPPORT |
| #define PARANOID(arg) \ |
| if ( arg == 0 ) {PyErr_SetString(ErrorObject, "Internal error: NULL arg!"); return 0; } |
| #else |
| #define PARANOID(arg) /*pass*/ |
| #endif |
| |
| /* Prototypes we use for routines and arguments */ |
| |
| typedef long anything; |
| typedef anything (*anyroutine)(...); |
| |
| /* Other constants */ |
| #define MAXNAME 31 /* Maximum size of names, for printing only */ |
| #define MAXARG 12 /* Maximum number of arguments */ |
| |
| /* |
| ** Routines to convert arguments between Python and C. |
| ** Note return-value converters return NULL if this argument (or return value) |
| ** doesn't return anything. The call-wrapper code collects all return values, |
| ** and does the expected thing based on the number of return values: return None, a single |
| ** value or a tuple of values. |
| ** |
| ** Hence, optional return values are also implementable. |
| */ |
| typedef anything (*py2c_converter)(PyObject *); |
| typedef PyObject *(*c2py_converter)(anything); |
| typedef PyObject *(*rv2py_converter)(anything); |
| |
| |
| /* Dummy routine for arguments that are output-only */ |
| static anything |
| py2c_dummy(arg) |
| PyObject *arg; |
| { |
| return 0; |
| } |
| |
| /* Routine to allocate storage for output integers */ |
| static anything |
| py2c_alloc(arg) |
| PyObject *arg; |
| { |
| char *ptr; |
| |
| if( (ptr=malloc(sizeof(anything))) == 0 ) |
| PyErr_NoMemory(); |
| return (anything)ptr; |
| } |
| |
| /* Dummy routine for arguments that are input-only */ |
| static PyObject * |
| c2py_dummy(arg) |
| anything arg; |
| { |
| return 0; |
| } |
| |
| /* Dummy routine for void return value */ |
| static PyObject * |
| rv2py_none(arg) |
| anything arg; |
| { |
| return 0; |
| } |
| |
| /* Routine to de-allocate storage for input-only arguments */ |
| static PyObject * |
| c2py_free(arg) |
| anything arg; |
| { |
| if ( arg ) |
| free((char *)arg); |
| return 0; |
| } |
| |
| /* |
| ** OSErr return value. |
| */ |
| static PyObject * |
| rv2py_oserr(arg) |
| anything arg; |
| { |
| OSErr err = (OSErr)arg; |
| |
| if (err) |
| return PyMac_Error(err); |
| return 0; |
| } |
| |
| /* |
| ** Input integers of all sizes (PPC only) |
| */ |
| static anything |
| py2c_in_int(arg) |
| PyObject *arg; |
| { |
| return PyInt_AsLong(arg); |
| } |
| |
| /* |
| ** Integer return values of all sizes (PPC only) |
| */ |
| static PyObject * |
| rv2py_int(arg) |
| anything arg; |
| { |
| return PyInt_FromLong((long)arg); |
| } |
| |
| /* |
| ** Integer output parameters |
| */ |
| static PyObject * |
| c2py_out_long(arg) |
| anything arg; |
| { |
| PyObject *rv; |
| |
| PARANOID(arg); |
| rv = PyInt_FromLong(*(long *)arg); |
| free((char *)arg); |
| return rv; |
| } |
| |
| static PyObject * |
| c2py_out_short(arg) |
| anything arg; |
| { |
| PyObject *rv; |
| |
| PARANOID(arg); |
| rv = PyInt_FromLong((long)*(short *)arg); |
| free((char *)arg); |
| return rv; |
| } |
| |
| static PyObject * |
| c2py_out_byte(arg) |
| anything arg; |
| { |
| PyObject *rv; |
| |
| PARANOID(arg); |
| rv = PyInt_FromLong((long)*(char *)arg); |
| free((char *)arg); |
| return rv; |
| } |
| |
| /* |
| ** Strings |
| */ |
| static anything |
| py2c_in_string(arg) |
| PyObject *arg; |
| { |
| return (anything)PyString_AsString(arg); |
| } |
| |
| /* |
| ** Pascal-style strings |
| */ |
| static anything |
| py2c_in_pstring(arg) |
| PyObject *arg; |
| { |
| unsigned char *p; |
| int size; |
| |
| if( (size = PyString_Size(arg)) < 0) |
| return 0; |
| if ( size > 255 ) { |
| PyErr_SetString(ErrorObject, "Pstring must be <= 255 chars"); |
| return 0; |
| } |
| if( (p=(unsigned char *)malloc(256)) == 0 ) { |
| PyErr_NoMemory(); |
| return 0; |
| } |
| p[0] = size; |
| memcpy(p+1, PyString_AsString(arg), size); |
| return (anything)p; |
| } |
| |
| static anything |
| py2c_out_pstring(arg) |
| PyObject *arg; |
| { |
| unsigned char *p; |
| |
| if( (p=(unsigned char *)malloc(256)) == 0 ) { |
| PyErr_NoMemory(); |
| return 0; |
| } |
| p[0] = 0; |
| return (anything)p; |
| } |
| |
| static PyObject * |
| c2py_out_pstring(arg) |
| anything arg; |
| { |
| unsigned char *p = (unsigned char *)arg; |
| PyObject *rv; |
| |
| PARANOID(arg); |
| rv = PyString_FromStringAndSize((char *)p+1, p[0]); |
| free(p); |
| return rv; |
| } |
| |
| static PyObject * |
| rv2py_pstring(arg) |
| anything arg; |
| { |
| unsigned char *p = (unsigned char *)arg; |
| PyObject *rv; |
| |
| if ( arg == NULL ) return NULL; |
| rv = PyString_FromStringAndSize((char *)p+1, p[0]); |
| return rv; |
| } |
| |
| /* |
| ** C objects. |
| */ |
| static anything |
| py2c_in_cobject(arg) |
| PyObject *arg; |
| { |
| if ( arg == Py_None ) |
| return 0; |
| return (anything)PyCObject_AsVoidPtr(arg); |
| } |
| |
| static PyObject * |
| c2py_out_cobject(arg) |
| anything arg; |
| { |
| void **ptr = (void **)arg; |
| PyObject *rv; |
| |
| PARANOID(arg); |
| if ( *ptr == 0 ) { |
| Py_INCREF(Py_None); |
| rv = Py_None; |
| } else { |
| rv = PyCObject_FromVoidPtr(*ptr, 0); |
| } |
| free((char *)ptr); |
| return rv; |
| } |
| |
| static PyObject * |
| rv2py_cobject(arg) |
| anything arg; |
| { |
| void *ptr = (void *)arg; |
| PyObject *rv; |
| |
| if ( ptr == 0 ) return NULL; |
| rv = PyCObject_FromVoidPtr(ptr, 0); |
| return rv; |
| } |
| |
| /* |
| ** Handles. |
| */ |
| static anything |
| py2c_in_handle(arg) |
| PyObject *arg; |
| { |
| Handle h = 0; |
| ResObj_Convert(arg, &h); |
| return (anything)h; |
| } |
| |
| static PyObject * |
| c2py_out_handle(arg) |
| anything arg; |
| { |
| Handle *rv = (Handle *)arg; |
| PyObject *prv; |
| |
| PARANOID(arg); |
| if ( *rv == 0 ) { |
| Py_INCREF(Py_None); |
| prv = Py_None; |
| } else { |
| prv = ResObj_New(*rv); |
| } |
| free((char *)rv); |
| return prv; |
| } |
| |
| static PyObject * |
| rv2py_handle(arg) |
| anything arg; |
| { |
| Handle rv = (Handle)arg; |
| |
| if ( rv == NULL ) return NULL; |
| return ResObj_New(rv); |
| } |
| |
| typedef struct { |
| char *name; /* Name */ |
| py2c_converter get; /* Get argument */ |
| int get_uses_arg; /* True if the above consumes an argument */ |
| c2py_converter put; /* Put result value */ |
| } conventry; |
| |
| static conventry converters[] = { |
| {"InByte", py2c_in_int, 1, c2py_dummy}, |
| {"InShort", py2c_in_int, 1, c2py_dummy}, |
| {"InLong", py2c_in_int, 1, c2py_dummy}, |
| {"OutLong", py2c_alloc, 0, c2py_out_long}, |
| {"OutShort", py2c_alloc, 0, c2py_out_short}, |
| {"OutByte", py2c_alloc, 0, c2py_out_byte}, |
| {"InString", py2c_in_string, 1, c2py_dummy}, |
| {"InPstring", py2c_in_pstring,1, c2py_free}, |
| {"OutPstring", py2c_out_pstring,0, c2py_out_pstring}, |
| {"InCobject", py2c_in_cobject,1, c2py_dummy}, |
| {"OutCobject", py2c_alloc, 0, c2py_out_cobject}, |
| {"InHandle", py2c_in_handle, 1, c2py_dummy}, |
| {"OutHandle", py2c_alloc, 0, c2py_out_handle}, |
| {0, 0, 0, 0} |
| }; |
| |
| typedef struct { |
| char *name; |
| rv2py_converter rtn; |
| } rvconventry; |
| |
| static rvconventry rvconverters[] = { |
| {"None", rv2py_none}, |
| {"OSErr", rv2py_oserr}, |
| {"Byte", rv2py_int}, |
| {"Short", rv2py_int}, |
| {"Long", rv2py_int}, |
| {"Pstring", rv2py_pstring}, |
| {"Cobject", rv2py_cobject}, |
| {"Handle", rv2py_handle}, |
| {0, 0} |
| }; |
| |
| static conventry * |
| getconverter(name) |
| char *name; |
| { |
| int i; |
| char buf[256]; |
| |
| for(i=0; converters[i].name; i++ ) |
| if ( strcmp(name, converters[i].name) == 0 ) |
| return &converters[i]; |
| sprintf(buf, "Unknown argtype: %s", name); |
| PyErr_SetString(ErrorObject, buf); |
| return 0; |
| } |
| |
| static rvconventry * |
| getrvconverter(name) |
| char *name; |
| { |
| int i; |
| char buf[256]; |
| |
| for(i=0; rvconverters[i].name; i++ ) |
| if ( strcmp(name, rvconverters[i].name) == 0 ) |
| return &rvconverters[i]; |
| sprintf(buf, "Unknown return value type: %s", name); |
| PyErr_SetString(ErrorObject, buf); |
| return 0; |
| } |
| |
| static int |
| argparse_conv(obj, ptr) |
| PyObject *obj; |
| conventry **ptr; |
| { |
| char *name; |
| int i; |
| conventry *item; |
| |
| if( (name=PyString_AsString(obj)) == NULL ) |
| return 0; |
| if( (item=getconverter(name)) == NULL ) |
| return 0; |
| *ptr = item; |
| return 1; |
| } |
| |
| static int |
| argparse_rvconv(obj, ptr) |
| PyObject *obj; |
| rvconventry **ptr; |
| { |
| char *name; |
| int i; |
| rvconventry *item; |
| |
| if( (name=PyString_AsString(obj)) == NULL ) |
| return 0; |
| if( (item=getrvconverter(name)) == NULL ) |
| return 0; |
| *ptr = item; |
| return 1; |
| } |
| |
| /* ----------------------------------------------------- */ |
| |
| /* Declarations for objects of type fragment */ |
| |
| typedef struct { |
| PyObject_HEAD |
| CFragConnectionID conn_id; |
| char name[MAXNAME+1]; |
| } cdfobject; |
| |
| staticforward PyTypeObject Cdftype; |
| |
| |
| |
| /* ---------------------------------------------------------------- */ |
| |
| /* Declarations for objects of type routine */ |
| |
| typedef struct { |
| PyObject_HEAD |
| anyroutine rtn; |
| char name[MAXNAME+1]; |
| } cdrobject; |
| |
| staticforward PyTypeObject Cdrtype; |
| |
| |
| |
| /* ---------------------------------------------------------------- */ |
| |
| /* Declarations for objects of type callable */ |
| |
| |
| typedef struct { |
| PyObject_HEAD |
| cdrobject *routine; /* The routine to call */ |
| int npargs; /* Python argument count */ |
| int ncargs; /* C argument count + 1 */ |
| rvconventry *rvconv; /* Return value converter */ |
| conventry *argconv[MAXARG]; /* Value converter list */ |
| } cdcobject; |
| |
| staticforward PyTypeObject Cdctype; |
| |
| |
| |
| /* -------------------------------------------------------- */ |
| |
| |
| static struct PyMethodDef cdr_methods[] = { |
| |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| /* ---------- */ |
| |
| |
| static cdrobject * |
| newcdrobject(name, routine) |
| unsigned char *name; |
| anyroutine routine; |
| { |
| cdrobject *self; |
| int nlen; |
| |
| self = PyObject_NEW(cdrobject, &Cdrtype); |
| if (self == NULL) |
| return NULL; |
| if ( name[0] > MAXNAME ) |
| nlen = MAXNAME; |
| else |
| nlen = name[0]; |
| memcpy(self->name, name+1, nlen); |
| self->name[nlen] = '\0'; |
| self->rtn = routine; |
| return self; |
| } |
| |
| static void |
| cdr_dealloc(self) |
| cdrobject *self; |
| { |
| PyMem_DEL(self); |
| } |
| |
| static PyObject * |
| cdr_repr(self) |
| cdrobject *self; |
| { |
| PyObject *s; |
| char buf[256]; |
| |
| sprintf(buf, "<Calldll routine %s address 0x%x>", self->name, self->rtn); |
| s = PyString_FromString(buf); |
| return s; |
| } |
| |
| static char Cdrtype__doc__[] = |
| "C Routine address" |
| ; |
| |
| static PyTypeObject Cdrtype = { |
| PyObject_HEAD_INIT(&PyType_Type) |
| 0, /*ob_size*/ |
| "routine", /*tp_name*/ |
| sizeof(cdrobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)cdr_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)0, /*tp_getattr*/ |
| (setattrfunc)0, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)cdr_repr, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| (ternaryfunc)0, /*tp_call*/ |
| (reprfunc)0, /*tp_str*/ |
| |
| /* Space for future expansion */ |
| 0L,0L,0L,0L, |
| Cdrtype__doc__ /* Documentation string */ |
| }; |
| |
| /* End of code for routine objects */ |
| /* -------------------------------------------------------- */ |
| |
| |
| static struct PyMethodDef cdc_methods[] = { |
| |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| /* ---------- */ |
| |
| |
| static cdcobject * |
| newcdcobject(routine, npargs, ncargs, rvconv, argconv) |
| cdrobject *routine; |
| int npargs; |
| int ncargs; |
| rvconventry *rvconv; |
| conventry *argconv[]; |
| { |
| cdcobject *self; |
| int i; |
| |
| self = PyObject_NEW(cdcobject, &Cdctype); |
| if (self == NULL) |
| return NULL; |
| self->routine = routine; |
| Py_INCREF(routine); |
| self->npargs = npargs; |
| self->ncargs = ncargs; |
| self->rvconv = rvconv; |
| for(i=0; i<MAXARG; i++) |
| if ( i < ncargs ) |
| self->argconv[i] = argconv[i]; |
| else |
| self->argconv[i] = 0; |
| return self; |
| } |
| |
| static void |
| cdc_dealloc(self) |
| cdcobject *self; |
| { |
| Py_XDECREF(self->routine); |
| PyMem_DEL(self); |
| } |
| |
| |
| static PyObject * |
| cdc_repr(self) |
| cdcobject *self; |
| { |
| PyObject *s; |
| char buf[256]; |
| int i; |
| |
| sprintf(buf, "<callable %s = %s(", self->rvconv->name, self->routine->name); |
| for(i=0; i< self->ncargs; i++) { |
| strcat(buf, self->argconv[i]->name); |
| if ( i < self->ncargs-1 ) |
| strcat(buf, ", "); |
| } |
| strcat(buf, ") >"); |
| |
| s = PyString_FromString(buf); |
| return s; |
| } |
| |
| /* |
| ** And this is what we all do it for: call a C function. |
| */ |
| static PyObject * |
| cdc_call(self, args, kwargs) |
| cdcobject *self; |
| PyObject *args; |
| PyObject *kwargs; |
| { |
| char buf[256]; |
| int i, pargindex; |
| anything c_args[MAXARG] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
| anything c_rv; |
| conventry *cp; |
| PyObject *curarg; |
| anyroutine func; |
| PyObject *returnvalues[MAXARG+1]; |
| PyObject *rv; |
| |
| if( kwargs ) { |
| PyErr_SetString(PyExc_TypeError, "Keyword args not allowed"); |
| return 0; |
| } |
| if( !PyTuple_Check(args) ) { |
| PyErr_SetString(PyExc_TypeError, "Arguments not in tuple"); |
| return 0; |
| } |
| if( PyTuple_Size(args) != self->npargs ) { |
| sprintf(buf, "%d arguments, expected %d", PyTuple_Size(args), self->npargs); |
| PyErr_SetString(PyExc_TypeError, buf); |
| return 0; |
| } |
| |
| /* Decode arguments */ |
| pargindex = 0; |
| for(i=0; i<self->ncargs; i++) { |
| cp = self->argconv[i]; |
| if ( cp->get_uses_arg ) { |
| curarg = PyTuple_GET_ITEM(args, pargindex); |
| pargindex++; |
| } else { |
| curarg = (PyObject *)NULL; |
| } |
| c_args[i] = (*cp->get)(curarg); |
| } |
| if (PyErr_Occurred()) |
| return 0; |
| |
| /* Call function */ |
| func = self->routine->rtn; |
| c_rv = (*func)(c_args[0], c_args[1], c_args[2], c_args[3], |
| c_args[4], c_args[5], c_args[6], c_args[7], |
| c_args[8], c_args[9], c_args[10], c_args[11]); |
| |
| /* Decode return value, and store into returnvalues if needed */ |
| pargindex = 0; |
| curarg = (*self->rvconv->rtn)(c_rv); |
| if ( curarg ) |
| returnvalues[pargindex++] = curarg; |
| |
| /* Decode returnvalue parameters and cleanup any storage allocated */ |
| for(i=0; i<self->ncargs; i++) { |
| cp = self->argconv[i]; |
| curarg = (*cp->put)(c_args[i]); |
| if(curarg) |
| returnvalues[pargindex++] = curarg; |
| /* NOTE: We only check errors at the end (so we free() everything) */ |
| } |
| if ( PyErr_Occurred() ) { |
| /* An error did occur. Free the python objects created */ |
| for(i=0; i<pargindex; i++) |
| Py_XDECREF(returnvalues[i]); |
| return NULL; |
| } |
| |
| /* Zero and one return values cases are special: */ |
| if ( pargindex == 0 ) { |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| if ( pargindex == 1 ) |
| return returnvalues[0]; |
| |
| /* More than one return value: put in a tuple */ |
| rv = PyTuple_New(pargindex); |
| for(i=0; i<pargindex; i++) |
| if(rv) |
| PyTuple_SET_ITEM(rv, i, returnvalues[i]); |
| else |
| Py_XDECREF(returnvalues[i]); |
| return rv; |
| } |
| |
| static char Cdctype__doc__[] = |
| "" |
| ; |
| |
| static PyTypeObject Cdctype = { |
| PyObject_HEAD_INIT(&PyType_Type) |
| 0, /*ob_size*/ |
| "callable", /*tp_name*/ |
| sizeof(cdcobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)cdc_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)0, /*tp_getattr*/ |
| (setattrfunc)0, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)cdc_repr, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| (ternaryfunc)cdc_call, /*tp_call*/ |
| (reprfunc)0, /*tp_str*/ |
| |
| /* Space for future expansion */ |
| 0L,0L,0L,0L, |
| Cdctype__doc__ /* Documentation string */ |
| }; |
| |
| /* End of code for callable objects */ |
| /* ---------------------------------------------------------------- */ |
| |
| static char cdf_keys__doc__[] = |
| "Return list of symbol names in fragment"; |
| |
| static PyObject * |
| cdf_keys(self, args) |
| cdfobject *self; |
| PyObject *args; |
| { |
| long symcount; |
| PyObject *rv, *obj; |
| Str255 symname; |
| Ptr dummy1; |
| CFragSymbolClass dummy2; |
| int i; |
| OSErr err; |
| |
| if (!PyArg_ParseTuple(args, "")) |
| return NULL; |
| if ( (err=CountSymbols(self->conn_id, &symcount)) < 0 ) |
| return PyMac_Error(err); |
| if ( (rv=PyList_New(symcount)) == NULL ) |
| return NULL; |
| for (i=0; i<symcount; i++) { |
| if ((err=GetIndSymbol(self->conn_id, i, symname, &dummy1, &dummy2)) < 0 ) { |
| Py_XDECREF(rv); |
| return PyMac_Error(err); |
| } |
| if ((obj=PyString_FromStringAndSize((char *)symname+1, symname[0])) == NULL ) { |
| Py_XDECREF(rv); |
| return PyMac_Error(err); |
| } |
| if (PyList_SetItem(rv, i, obj) < 0 ) { |
| Py_XDECREF(rv); |
| return NULL; |
| } |
| } |
| return rv; |
| } |
| |
| |
| static struct PyMethodDef cdf_methods[] = { |
| {"keys", (PyCFunction)cdf_keys, METH_VARARGS, |
| cdf_keys__doc__}, |
| |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| /* ---------- */ |
| |
| |
| static cdfobject * |
| newcdfobject(conn_id, name) |
| CFragConnectionID conn_id; |
| unsigned char *name; |
| { |
| cdfobject *self; |
| int nlen; |
| |
| self = PyObject_NEW(cdfobject, &Cdftype); |
| if (self == NULL) |
| return NULL; |
| self->conn_id = conn_id; |
| if ( name[0] > MAXNAME ) |
| nlen = MAXNAME; |
| else |
| nlen = name[0]; |
| strncpy(self->name, (char *)name+1, nlen); |
| self->name[nlen] = '\0'; |
| return self; |
| } |
| |
| static void |
| cdf_dealloc(self) |
| cdfobject *self; |
| { |
| PyMem_DEL(self); |
| } |
| |
| static PyObject * |
| cdf_repr(self) |
| cdfobject *self; |
| { |
| PyObject *s; |
| char buf[256]; |
| |
| sprintf(buf, "<fragment %s connection, id 0x%x>", self->name, self->conn_id); |
| s = PyString_FromString(buf); |
| return s; |
| } |
| |
| static PyObject * |
| cdf_getattr_helper(self, name) |
| cdfobject *self; |
| char *name; |
| { |
| unsigned char *rtn_name; |
| anyroutine rtn; |
| OSErr err; |
| Str255 errMessage; |
| CFragSymbolClass class; |
| char buf[256]; |
| |
| rtn_name = Pstring(name); |
| err = FindSymbol(self->conn_id, rtn_name, (Ptr *)&rtn, &class); |
| if ( err ) { |
| sprintf(buf, "%.*s: %s", rtn_name[0], rtn_name+1, PyMac_StrError(err)); |
| PyErr_SetString(ErrorObject, buf); |
| return NULL; |
| } |
| if( class != kTVectorCFragSymbol ) { |
| PyErr_SetString(ErrorObject, "Symbol is not a routine"); |
| return NULL; |
| } |
| |
| return (PyObject *)newcdrobject(rtn_name, rtn); |
| } |
| |
| static PyObject * |
| cdf_getattr(self, name) |
| cdfobject *self; |
| char *name; |
| { |
| PyObject *rv; |
| |
| if ((rv=Py_FindMethod(cdf_methods, (PyObject *)self, name))) |
| return rv; |
| PyErr_Clear(); |
| return cdf_getattr_helper(self, name); |
| } |
| |
| /* -------------------------------------------------------- */ |
| /* Code to access cdf objects as mappings */ |
| |
| static int |
| cdf_length(self) |
| cdfobject *self; |
| { |
| long symcount; |
| OSErr err; |
| |
| err = CountSymbols(self->conn_id, &symcount); |
| if ( err ) { |
| PyMac_Error(err); |
| return -1; |
| } |
| return symcount; |
| } |
| |
| static PyObject * |
| cdf_subscript(self, key) |
| cdfobject *self; |
| PyObject *key; |
| { |
| char *name; |
| |
| if ((name=PyString_AsString(key)) == 0 ) |
| return 0; |
| return cdf_getattr_helper(self, name); |
| } |
| |
| static int |
| cdf_ass_sub(self, v, w) |
| cdfobject *self; |
| PyObject *v, *w; |
| { |
| /* XXXX Put w in self under key v */ |
| return 0; |
| } |
| |
| static PyMappingMethods cdf_as_mapping = { |
| (inquiry)cdf_length, /*mp_length*/ |
| (binaryfunc)cdf_subscript, /*mp_subscript*/ |
| (objobjargproc)cdf_ass_sub, /*mp_ass_subscript*/ |
| }; |
| |
| /* -------------------------------------------------------- */ |
| |
| static char Cdftype__doc__[] = |
| "Code Fragment library symbol table" |
| ; |
| |
| static PyTypeObject Cdftype = { |
| PyObject_HEAD_INIT(&PyType_Type) |
| 0, /*ob_size*/ |
| "fragment", /*tp_name*/ |
| sizeof(cdfobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)cdf_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)cdf_getattr, /*tp_getattr*/ |
| (setattrfunc)0, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)cdf_repr, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| &cdf_as_mapping, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| (ternaryfunc)0, /*tp_call*/ |
| (reprfunc)0, /*tp_str*/ |
| |
| /* Space for future expansion */ |
| 0L,0L,0L,0L, |
| Cdftype__doc__ /* Documentation string */ |
| }; |
| |
| /* End of code for fragment objects */ |
| /* -------------------------------------------------------- */ |
| |
| |
| static char cdll_getlibrary__doc__[] = |
| "Load a shared library fragment and return the symbol table" |
| ; |
| |
| static PyObject * |
| cdll_getlibrary(self, args) |
| PyObject *self; /* Not used */ |
| PyObject *args; |
| { |
| Str255 frag_name; |
| OSErr err; |
| Str255 errMessage; |
| Ptr main_addr; |
| CFragConnectionID conn_id; |
| char buf[256]; |
| |
| if (!PyArg_ParseTuple(args, "O&", PyMac_GetStr255, frag_name)) |
| return NULL; |
| |
| /* Find the library connection ID */ |
| err = GetSharedLibrary(frag_name, kCompiledCFragArch, kLoadCFrag, &conn_id, &main_addr, |
| errMessage); |
| if ( err ) { |
| sprintf(buf, "%.*s: %s", errMessage[0], errMessage+1, PyMac_StrError(err)); |
| PyErr_SetString(ErrorObject, buf); |
| return NULL; |
| } |
| return (PyObject *)newcdfobject(conn_id, frag_name); |
| } |
| |
| static char cdll_getdiskfragment__doc__[] = |
| "Load a fragment from a disk file and return the symbol table" |
| ; |
| |
| static PyObject * |
| cdll_getdiskfragment(self, args) |
| PyObject *self; /* Not used */ |
| PyObject *args; |
| { |
| FSSpec fsspec; |
| Str255 frag_name; |
| OSErr err; |
| Str255 errMessage; |
| Ptr main_addr; |
| CFragConnectionID conn_id; |
| char buf[256]; |
| Boolean isfolder, didsomething; |
| |
| if (!PyArg_ParseTuple(args, "O&O&", PyMac_GetFSSpec, &fsspec, |
| PyMac_GetStr255, frag_name)) |
| return NULL; |
| err = ResolveAliasFile(&fsspec, 1, &isfolder, &didsomething); |
| if ( err ) |
| return PyErr_Mac(ErrorObject, err); |
| |
| /* Load the fragment (or return the connID if it is already loaded */ |
| err = GetDiskFragment(&fsspec, 0, 0, frag_name, |
| kLoadCFrag, &conn_id, &main_addr, |
| errMessage); |
| if ( err ) { |
| sprintf(buf, "%.*s: %s", errMessage[0], errMessage+1, PyMac_StrError(err)); |
| PyErr_SetString(ErrorObject, buf); |
| return NULL; |
| } |
| return (PyObject *)newcdfobject(conn_id, frag_name); |
| } |
| |
| static char cdll_newcall__doc__[] = |
| "" |
| ; |
| |
| static PyObject * |
| cdll_newcall(self, args) |
| PyObject *self; /* Not used */ |
| PyObject *args; |
| { |
| cdrobject *routine; |
| conventry *argconv[MAXARG] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
| rv2py_converter rvconv; |
| int npargs, ncargs; |
| |
| /* Note: the next format depends on MAXARG */ |
| if (!PyArg_ParseTuple(args, "O!O&|O&O&O&O&O&O&O&O&O&O&O&O&", &Cdrtype, &routine, |
| argparse_rvconv, &rvconv, |
| argparse_conv, &argconv[0], argparse_conv, &argconv[1], |
| argparse_conv, &argconv[2], argparse_conv, &argconv[3], |
| argparse_conv, &argconv[4], argparse_conv, &argconv[5], |
| argparse_conv, &argconv[6], argparse_conv, &argconv[7], |
| argparse_conv, &argconv[8], argparse_conv, &argconv[9], |
| argparse_conv, &argconv[10], argparse_conv, &argconv[11])) |
| return NULL; |
| npargs = 0; |
| for(ncargs=0; ncargs < MAXARG && argconv[ncargs]; ncargs++) { |
| if( argconv[ncargs]->get_uses_arg ) npargs++; |
| } |
| return (PyObject *)newcdcobject(routine, npargs, ncargs, rvconv, argconv); |
| } |
| |
| /* List of methods defined in the module */ |
| |
| static struct PyMethodDef cdll_methods[] = { |
| {"getlibrary", (PyCFunction)cdll_getlibrary, METH_VARARGS, |
| cdll_getlibrary__doc__}, |
| {"getdiskfragment", (PyCFunction)cdll_getdiskfragment, METH_VARARGS, |
| cdll_getdiskfragment__doc__}, |
| {"newcall", (PyCFunction)cdll_newcall, METH_VARARGS, |
| cdll_newcall__doc__}, |
| |
| {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ |
| }; |
| |
| |
| /* Initialization function for the module (*must* be called initcalldll) */ |
| |
| static char calldll_module_documentation[] = |
| "" |
| ; |
| |
| void |
| initcalldll() |
| { |
| PyObject *m, *d; |
| |
| /* Create the module and add the functions */ |
| m = Py_InitModule4("calldll", cdll_methods, |
| calldll_module_documentation, |
| (PyObject*)NULL,PYTHON_API_VERSION); |
| |
| /* Add some symbolic constants to the module */ |
| d = PyModule_GetDict(m); |
| ErrorObject = PyString_FromString("calldll.error"); |
| PyDict_SetItemString(d, "error", ErrorObject); |
| |
| /* XXXX Add constants here */ |
| |
| /* Check for errors */ |
| if (PyErr_Occurred()) |
| Py_FatalError("can't initialize module calldll"); |
| } |
| |
| #ifdef TESTSUPPORT |
| |
| /* Test routine */ |
| int cdll_b_bbbbbbbb(char a1,char a2,char a3,char a4,char a5,char a6,char a7,char a8) |
| { |
| return a1+a2+a3+a4+a5+a6+a7+a8; |
| } |
| |
| short cdll_h_hhhhhhhh(short a1,short a2,short a3,short a4,short a5,short a6,short a7,short a8) |
| { |
| return a1+a2+a3+a4+a5+a6+a7+a8; |
| } |
| |
| int cdll_l_llllllll(int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8) |
| { |
| return a1+a2+a3+a4+a5+a6+a7+a8; |
| } |
| |
| void cdll_N_ssssssss(char *a1,char *a2,char *a3,char *a4,char *a5,char *a6,char *a7,char *a8) |
| { |
| printf("cdll_N_ssssssss args: %s %s %s %s %s %s %s %s\n", a1, a2, a3, a4, |
| a5, a6, a7, a8); |
| } |
| |
| OSErr cdll_o_l(long l) |
| { |
| return (OSErr)l; |
| } |
| |
| void cdll_N_pp(unsigned char *in, unsigned char *out) |
| { |
| out[0] = in[0] + 5; |
| strcpy((char *)out+1, "Was: "); |
| memcpy(out+6, in+1, in[0]); |
| } |
| |
| void cdll_N_bb(char a1, char *a2) |
| { |
| *a2 = a1; |
| } |
| |
| void cdll_N_hh(short a1, short *a2) |
| { |
| *a2 = a1; |
| } |
| |
| void cdll_N_ll(long a1, long *a2) |
| { |
| *a2 = a1; |
| } |
| |
| void cdll_N_sH(char *a1, Handle a2) |
| { |
| int len; |
| |
| len = strlen(a1); |
| SetHandleSize(a2, len); |
| HLock(a2); |
| memcpy(*a2, a1, len); |
| HUnlock(a2); |
| } |
| #endif |