mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1194 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1194 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /***********************************************************
 | |
| 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
 | 
