diff options
-rw-r--r-- | Include/longobject.h | 2 | ||||
-rw-r--r-- | Modules/structmodule.c | 31 | ||||
-rw-r--r-- | Objects/longobject.c | 55 | ||||
-rw-r--r-- | PC/config.h | 6 | ||||
-rw-r--r-- | PC/python_nt.def | 2 |
5 files changed, 96 insertions, 0 deletions
diff --git a/Include/longobject.h b/Include/longobject.h index d9bc086..afb8af1 100644 --- a/Include/longobject.h +++ b/Include/longobject.h @@ -49,6 +49,8 @@ extern PyObject *PyLong_FromDouble Py_PROTO((double)); extern long PyLong_AsLong Py_PROTO((PyObject *)); extern unsigned long PyLong_AsUnsignedLong Py_PROTO((PyObject *)); extern double PyLong_AsDouble Py_PROTO((PyObject *)); +extern PyObject *PyLong_FromVoidPtr Py_PROTO((void *)); +extern void *PyLong_AsVoidPtr Py_PROTO((PyObject *)); #ifdef HAVE_LONG_LONG #ifndef LONG_LONG diff --git a/Modules/structmodule.c b/Modules/structmodule.c index af8f1e5..a20d5ff 100644 --- a/Modules/structmodule.c +++ b/Modules/structmodule.c @@ -53,6 +53,8 @@ these can be preceded by a decimal repeat count:\n\ l:long; L:unsigned long; f:float; d:double.\n\ Special cases (preceding decimal count indicates length):\n\ s:string (array of char); p: pascal string (w. count byte).\n\ +Special case (only available in native format):\n\ + P:an integer type that is wide enough to hold a pointer.\n\ Whitespace between formats is ignored.\n\ \n\ The variable struct.error is an exception raised on errors."; @@ -86,12 +88,14 @@ typedef struct { char c; int x; } s_int; typedef struct { char c; long x; } s_long; typedef struct { char c; float x; } s_float; typedef struct { char c; double x; } s_double; +typedef struct { char c; void *x; } s_void_p; #define SHORT_ALIGN (sizeof(s_short) - sizeof(short)) #define INT_ALIGN (sizeof(s_int) - sizeof(int)) #define LONG_ALIGN (sizeof(s_long) - sizeof(long)) #define FLOAT_ALIGN (sizeof(s_float) - sizeof(float)) #define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double)) +#define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void *)) #ifdef __powerc #pragma options align=reset @@ -523,6 +527,14 @@ nu_double(p, f) return PyFloat_FromDouble(x); } +static PyObject * +nu_void_p(p, f) + const char *p; + const formatdef *f; +{ + return PyLong_FromVoidPtr(*(void **)p); +} + static int np_byte(p, v, f) char *p; @@ -648,6 +660,24 @@ np_double(p, v, f) return 0; } +static int +np_void_p(p, v, f) + char *p; + PyObject *v; + const formatdef *f; +{ + void *x = PyLong_AsVoidPtr(v); + if (x == NULL && PyErr_Occurred()) { + /* ### hrm. PyLong_AsVoidPtr raises SystemError */ + if (PyErr_ExceptionMatches(PyExc_TypeError)) + PyErr_SetString(StructError, + "required argument is not an integer"); + return -1; + } + *(void **)p = x; + return 0; +} + static formatdef native_table[] = { {'x', sizeof(char), 0, NULL}, {'b', sizeof(char), 0, nu_byte, np_byte}, @@ -663,6 +693,7 @@ static formatdef native_table[] = { {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong}, {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, + {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, {0} }; diff --git a/Objects/longobject.c b/Objects/longobject.c index 5a09255..7dbb542 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -277,6 +277,61 @@ PyLong_AsDouble(vv) return x * sign; } +/* Create a new long (or int) object from a C pointer */ + +PyObject * +PyLong_FromVoidPtr(p) + void *p; +{ +#if SIZEOF_VOID_P == SIZEOF_LONG + return PyInt_FromLong((long)p); +#else + /* optimize null pointers */ + if ( p == NULL ) + return PyInt_FromLong(0); + + /* we can assume that HAVE_LONG_LONG is true. if not, then the + configuration process should have bailed (having big pointers + without long longs seems non-sensical) */ + return PyLong_FromLongLong((LONG_LONG)p); +#endif /* SIZEOF_VOID_P == SIZEOF_LONG */ +} + +/* Get a C pointer from a long object (or an int object in some cases) */ + +void * +PyLong_AsVoidPtr(vv) + PyObject *vv; +{ + /* This function will allow int or long objects. If vv is neither, + then the PyLong_AsLong*() functions will raise the exception: + PyExc_SystemError, "bad argument to internal function" + */ + +#if SIZEOF_VOID_P == SIZEOF_LONG + long x; + + if ( PyInt_Check(vv) ) + x = PyInt_AS_LONG(vv); + else + x = PyLong_AsLong(vv); +#else + /* we can assume that HAVE_LONG_LONG is true. if not, then the + configuration process should have bailed (having big pointers + without long longs seems non-sensical) */ + LONG_LONG x; + + if ( PyInt_Check(vv) ) + x = PyInt_AS_LONG(vv); + else + x = PyLong_AsLongLong(vv); +#endif /* SIZEOF_VOID_P == SIZEOF_LONG */ + + if (x == -1 && PyErr_Occurred()) + return NULL; + return (void *)x; +} + #ifdef HAVE_LONG_LONG /* * LONG_LONG support by Chris Herborth (chrish@qnx.com) diff --git a/PC/config.h b/PC/config.h index b043df5..0818746 100644 --- a/PC/config.h +++ b/PC/config.h @@ -213,6 +213,12 @@ typedef int pid_t; #define SIZEOF_LONG 4 #define SIZEOF_LONG_LONG 8 +#ifdef _M_ALPHA +#define SIZEOF_VOID_P 8 +#else +#define SIZEOF_VOID_P 4 +#endif + /* EXPERIMENTAL FEATURE: When CHECK_IMPORT_CASE is defined, check case of imported modules against case of file; this causes "import String" to fail with a NameError exception when it finds "string.py". Normally, you set diff --git a/PC/python_nt.def b/PC/python_nt.def index 323a935..f56ec66 100644 --- a/PC/python_nt.def +++ b/PC/python_nt.def @@ -215,12 +215,14 @@ EXPORTS PyLong_AsLongLong PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong + PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromString PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong + PyLong_FromVoidPtr PyMapping_Check PyMapping_GetItemString PyMapping_HasKey |