diff options
Diffstat (limited to 'Modules')
71 files changed, 3513 insertions, 1251 deletions
diff --git a/Modules/Setup.dist b/Modules/Setup.dist index 49c8425..1b2502d 100644 --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -167,7 +167,7 @@ GLHACK=-Dclear=__GLclear #array arraymodule.c # array objects #cmath cmathmodule.c # -lm # complex math library functions #math mathmodule.c # -lm # math library functions, e.g. sin() -#struct structmodule.c # binary structure packing/unpacking +#_struct _struct.c # binary structure packing/unpacking #time timemodule.c # -lm # time operations and variables #operator operator.c # operator.add() and similar goodies #_weakref _weakref.c # basic weak reference support diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index 39b443b..d8d23c4 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -169,7 +169,7 @@ codec_decode(PyObject *self, PyObject *args) static PyObject *codec_tuple(PyObject *unicode, - int len) + Py_ssize_t len) { PyObject *v,*w; @@ -181,7 +181,7 @@ PyObject *codec_tuple(PyObject *unicode, return NULL; } PyTuple_SET_ITEM(v,0,unicode); - w = PyInt_FromLong(len); + w = PyInt_FromSsize_t(len); if (w == NULL) { Py_DECREF(v); return NULL; @@ -213,7 +213,7 @@ escape_encode(PyObject *self, PyObject *str; const char *errors = NULL; char *buf; - int len; + Py_ssize_t len; if (!PyArg_ParseTuple(args, "O!|z:escape_encode", &PyString_Type, &str, &errors)) @@ -319,12 +319,11 @@ utf_16_decode(PyObject *self, if (!PyArg_ParseTuple(args, "t#|zi:utf_16_decode", &data, &size, &errors, &final)) return NULL; - /* XXX Why is consumed initialized to size? mvl */ if (size < 0) { PyErr_SetString(PyExc_ValueError, "negative argument"); return 0; } - consumed = size; + consumed = size; /* This is overwritten unless final is true. */ decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, final ? NULL : &consumed); if (decoded == NULL) @@ -348,12 +347,11 @@ utf_16_le_decode(PyObject *self, &data, &size, &errors, &final)) return NULL; - /* XXX Why is consumed initialized to size? mvl */ if (size < 0) { PyErr_SetString(PyExc_ValueError, "negative argument"); return 0; } - consumed = size; + consumed = size; /* This is overwritten unless final is true. */ decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, final ? NULL : &consumed); if (decoded == NULL) @@ -377,12 +375,11 @@ utf_16_be_decode(PyObject *self, if (!PyArg_ParseTuple(args, "t#|zi:utf_16_be_decode", &data, &size, &errors, &final)) return NULL; - /* XXX Why is consumed initialized to size? mvl */ if (size < 0) { PyErr_SetString(PyExc_ValueError, "negative argument"); return 0; } - consumed = size; + consumed = size; /* This is overwritten unless final is true. */ decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, final ? NULL : &consumed); if (decoded == NULL) @@ -413,12 +410,11 @@ utf_16_ex_decode(PyObject *self, if (!PyArg_ParseTuple(args, "t#|zii:utf_16_ex_decode", &data, &size, &errors, &byteorder, &final)) return NULL; - /* XXX Why is consumed initialized to size? mvl */ if (size < 0) { PyErr_SetString(PyExc_ValueError, "negative argument"); return 0; } - consumed = size; + consumed = size; /* This is overwritten unless final is true. */ unicode = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, final ? NULL : &consumed); if (unicode == NULL) diff --git a/Modules/_csv.c b/Modules/_csv.c index 4704c16..a341eb4 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1104,6 +1104,8 @@ join_append_lineterminator(WriterObj *self) char *terminator; terminator_len = PyString_Size(self->dialect->lineterminator); + if (terminator_len == -1) + return 0; /* grow record buffer if necessary */ if (!join_check_rec_size(self, self->rec_len + terminator_len)) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index e6d6aa4..eaa3ced 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1223,6 +1223,19 @@ c_void_p_from_param(PyObject *type, PyObject *value) return value; } } +/* function pointer */ + if (CFuncPtrObject_Check(value)) { + PyCArgObject *parg; + CFuncPtrObject *func; + func = (CFuncPtrObject *)value; + parg = new_CArgObject(); + parg->pffi_type = &ffi_type_pointer; + parg->tag = 'P'; + Py_INCREF(value); + parg->value.p = *(void **)func->b_ptr; + parg->obj = value; + return (PyObject *)parg; + } /* c_char_p, c_wchar_p */ stgd = PyObject_stgdict(value); if (stgd && CDataObject_Check(value) && stgd->proto && PyString_Check(stgd->proto)) { @@ -2172,7 +2185,7 @@ _CData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, only it's object list. So we create a tuple, containing b_objects list PLUS the array itself, and return that! */ - return Py_BuildValue("(OO)", keep, value); + return PyTuple_Pack(2, keep, value); } PyErr_Format(PyExc_TypeError, "incompatible types, %s instance instead of %s instance", @@ -4405,6 +4418,8 @@ cast_check_pointertype(PyObject *arg) if (PointerTypeObject_Check(arg)) return 1; + if (CFuncPtrTypeObject_Check(arg)) + return 1; dict = PyType_stgdict(arg); if (dict) { if (PyString_Check(dict->proto) @@ -4564,7 +4579,7 @@ init_ctypes(void) #endif PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL)); PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI)); - PyModule_AddStringConstant(m, "__version__", "0.9.9.4"); + PyModule_AddStringConstant(m, "__version__", "0.9.9.6"); PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset)); diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index ad3b047..b10d6fe 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -96,6 +96,11 @@ EXPORT(char *) my_strdup(char *src) return dst; } +EXPORT(void)my_free(void *ptr) +{ + free(ptr); +} + #ifdef HAVE_WCHAR_H EXPORT(wchar_t *) my_wcsdup(wchar_t *src) { @@ -199,11 +204,6 @@ EXPORT(int) _testfunc_ppp(char ***p) return 0; } -EXPORT(void) my_free(void *p) -{ - printf("my_free got %p\n", p); -} - typedef struct { char *name; char *value; diff --git a/Modules/_ctypes/libffi/configure b/Modules/_ctypes/libffi/configure index c1e5cd4..9fdd654 100755 --- a/Modules/_ctypes/libffi/configure +++ b/Modules/_ctypes/libffi/configure @@ -310,7 +310,7 @@ ac_includes_default="\ # include <unistd.h> #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC ac_ct_CC EXEEXT OBJEXT CFLAGS CPP CPPFLAGS EGREP ALLOCA HAVE_LONG_DOUBLE TARGET TARGETDIR LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC ac_ct_CC EXEEXT OBJEXT CFLAGS CPP CPPFLAGS EGREP ALLOCA HAVE_LONG_DOUBLE TARGET TARGETDIR MKTARGET LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -3483,6 +3483,7 @@ fi TARGETDIR="unknown" case "$host" in +i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;; i*86-*-linux*) TARGET=X86; TARGETDIR=x86;; i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;; i*86-*-solaris2.1[0-9]*) TARGET=X86_64; TARGETDIR=x86;; @@ -3534,6 +3535,8 @@ echo "$as_me: error: \"libffi has not been ported to $host.\"" >&2;} { (exit 1); exit 1; }; } fi +MKTARGET=$TARGET + case x$TARGET in xMIPS*) TARGET=MIPS ;; *) ;; @@ -5241,6 +5244,9 @@ presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} esac + + + if test x$TARGET = xSPARC; then echo "$as_me:$LINENO: checking assembler and linker support unaligned pc related relocs" >&5 echo $ECHO_N "checking assembler and linker support unaligned pc related relocs... $ECHO_C" >&6 @@ -5457,6 +5463,7 @@ fi + cat >>confdefs.h <<\_ACEOF #define FFI_NO_RAW_API 1 _ACEOF @@ -5467,7 +5474,15 @@ _ACEOF ac_config_commands="$ac_config_commands src" - ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h" +TARGETINCDIR=$TARGETDIR +case $host in +*-*-darwin*) + TARGETINCDIR="darwin" + ;; +esac + + + ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h" ac_config_links="$ac_config_links include/ffi_common.h:include/ffi_common.h" @@ -6014,7 +6029,7 @@ do # Handling of arguments. "include/ffi.h" ) CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;; "fficonfig.py" ) CONFIG_FILES="$CONFIG_FILES fficonfig.py" ;; - "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;; + "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h" ;; "include/ffi_common.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffi_common.h:include/ffi_common.h" ;; "include" ) CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;; "src" ) CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;; @@ -6129,6 +6144,7 @@ s,@ALLOCA@,$ALLOCA,;t t s,@HAVE_LONG_DOUBLE@,$HAVE_LONG_DOUBLE,;t t s,@TARGET@,$TARGET,;t t s,@TARGETDIR@,$TARGETDIR,;t t +s,@MKTARGET@,$MKTARGET,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF diff --git a/Modules/_ctypes/libffi/configure.ac b/Modules/_ctypes/libffi/configure.ac index c7f05d6..a0d7513 100644 --- a/Modules/_ctypes/libffi/configure.ac +++ b/Modules/_ctypes/libffi/configure.ac @@ -21,6 +21,7 @@ AC_FUNC_MMAP_BLACKLIST TARGETDIR="unknown" case "$host" in +i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;; i*86-*-linux*) TARGET=X86; TARGETDIR=x86;; i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;; i*86-*-solaris2.1[[0-9]]*) TARGET=X86_64; TARGETDIR=x86;; @@ -70,6 +71,12 @@ if test $TARGETDIR = unknown; then AC_MSG_ERROR(["libffi has not been ported to $host."]) fi +dnl libffi changes TARGET for MIPS to define a such macro in the header +dnl while MIPS_IRIX or MIPS_LINUX is separatedly used to decide which +dnl files will be compiled. So, we need to keep the original decision +dnl of TARGET to use in fficonfig.py.in. +MKTARGET=$TARGET + case x$TARGET in xMIPS*) TARGET=MIPS ;; *) ;; @@ -93,6 +100,24 @@ fi AC_SUBST(HAVE_LONG_DOUBLE) AC_C_BIGENDIAN +AH_VERBATIM([WORDS_BIGENDIAN], +[ +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). + + The block below does compile-time checking for endianness on platforms + that use GCC and therefore allows compiling fat binaries on OSX by using + '-arch ppc -arch i386' as the compile flags. The phrasing was choosen + such that the configure-result is used on systems that don't use GCC. +*/ +#ifdef __BIG_ENDIAN__ +#define WORDS_BIGENDIAN 1 +#else +#ifndef __LITTLE_ENDIAN__ +#undef WORDS_BIGENDIAN +#endif +#endif]) + if test x$TARGET = xSPARC; then AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs], @@ -183,6 +208,7 @@ AH_BOTTOM([ AC_SUBST(TARGET) AC_SUBST(TARGETDIR) +AC_SUBST(MKTARGET) AC_SUBST(SHELL) @@ -194,7 +220,15 @@ test -d src || mkdir src test -d src/$TARGETDIR || mkdir src/$TARGETDIR ], [TARGETDIR="$TARGETDIR"]) -AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h) +TARGETINCDIR=$TARGETDIR +case $host in +*-*-darwin*) + TARGETINCDIR="darwin" + ;; +esac + + +AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h) AC_CONFIG_LINKS(include/ffi_common.h:include/ffi_common.h) AC_CONFIG_FILES(include/ffi.h fficonfig.py) diff --git a/Modules/_ctypes/libffi/fficonfig.h.in b/Modules/_ctypes/libffi/fficonfig.h.in index 0fd2db5..bcc5a58 100644 --- a/Modules/_ctypes/libffi/fficonfig.h.in +++ b/Modules/_ctypes/libffi/fficonfig.h.in @@ -114,9 +114,22 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS + /* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ + first (like Motorola and SPARC, unlike Intel and VAX). + + The block below does compile-time checking for endianness on platforms + that use GCC and therefore allows compiling fat binaries on OSX by using + '-arch ppc -arch i386' as the compile flags. The phrasing was choosen + such that the configure-result is used on systems that don't use GCC. +*/ +#ifdef __BIG_ENDIAN__ +#define WORDS_BIGENDIAN 1 +#else +#ifndef __LITTLE_ENDIAN__ #undef WORDS_BIGENDIAN +#endif +#endif #ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE diff --git a/Modules/_ctypes/libffi/fficonfig.py.in b/Modules/_ctypes/libffi/fficonfig.py.in index 2ed2347..3364049 100644 --- a/Modules/_ctypes/libffi/fficonfig.py.in +++ b/Modules/_ctypes/libffi/fficonfig.py.in @@ -6,6 +6,7 @@ ffi_platforms = { 'MIPS_IRIX': ['src/mips/ffi.c', 'src/mips/o32.S', 'src/mips/n32.S'], 'MIPS_LINUX': ['src/mips/ffi.c', 'src/mips/o32.S'], 'X86': ['src/x86/ffi.c', 'src/x86/sysv.S'], + 'X86_DARWIN': ['src/x86/ffi_darwin.c', 'src/x86/darwin.S'], 'X86_WIN32': ['src/x86/ffi.c', 'src/x86/win32.S'], 'SPARC': ['src/sparc/ffi.c', 'src/sparc/v8.S', 'src/sparc/v9.S'], 'ALPHA': ['src/alpha/ffi.c', 'src/alpha/osf.S'], @@ -26,10 +27,22 @@ ffi_platforms = { 'PA': ['src/pa/linux.S', 'src/pa/ffi.c'], } +# Build all darwin related files on all supported darwin architectures, this +# makes it easier to build universal binaries. +if 1: + all_darwin = ('X86_DARWIN', 'POWERPC_DARWIN') + all_darwin_files = [] + for pn in all_darwin: + all_darwin_files.extend(ffi_platforms[pn]) + for pn in all_darwin: + ffi_platforms[pn] = all_darwin_files + del all_darwin, all_darwin_files, pn + ffi_srcdir = '@srcdir@' -ffi_sources += ffi_platforms['@TARGET@'] +ffi_sources += ffi_platforms['@MKTARGET@'] ffi_sources = [os.path.join('@srcdir@', f) for f in ffi_sources] ffi_cflags = '@CFLAGS@' +# I think this may no longer be needed: if sys.platform == "openbsd3": ffi_cflags += " -fno-stack-protector" diff --git a/Modules/_ctypes/libffi/src/darwin/ffitarget.h b/Modules/_ctypes/libffi/src/darwin/ffitarget.h new file mode 100644 index 0000000..2dc308a --- /dev/null +++ b/Modules/_ctypes/libffi/src/darwin/ffitarget.h @@ -0,0 +1,25 @@ +/* + * This file is for MacOSX only. Dispatch to the right architecture include + * file based on the current archictecture (instead of relying on a symlink + * created by configure). This makes is possible to build a univeral binary + * of ctypes in one go. + */ +#if defined(__i386__) + +#ifndef X86_DARWIN +#define X86_DARWIN +#endif +#undef POWERPC_DARWIN + +#include "../src/x86/ffitarget.h" + +#elif defined(__ppc__) + +#ifndef POWERPC_DARWIN +#define POWERPC_DARWIN +#endif +#undef X86_DARWIN + +#include "../src/powerpc/ffitarget.h" + +#endif diff --git a/Modules/_ctypes/libffi/src/powerpc/darwin.S b/Modules/_ctypes/libffi/src/powerpc/darwin.S index d8a1df5..917dc93 100644 --- a/Modules/_ctypes/libffi/src/powerpc/darwin.S +++ b/Modules/_ctypes/libffi/src/powerpc/darwin.S @@ -1,3 +1,4 @@ +#ifdef __ppc__ /* ----------------------------------------------------------------------- darwin.S - Copyright (c) 2000 John Hornkvist Copyright (c) 2004 Free Software Foundation, Inc. @@ -243,3 +244,4 @@ LEFDE1: .align LOG2_GPR_BYTES LLFB0$non_lazy_ptr: .g_long LFB0 +#endif diff --git a/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S b/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S index 6d9a364..71054f5 100644 --- a/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S +++ b/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S @@ -1,3 +1,4 @@ +#ifdef __ppc__ /* ----------------------------------------------------------------------- darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, Inc. based on ppc_closure.S @@ -315,3 +316,4 @@ L_ffi_closure_helper_DARWIN$lazy_ptr: .align LOG2_GPR_BYTES LLFB1$non_lazy_ptr: .g_long LFB1 +#endif diff --git a/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c b/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c index d758f8f..1595b00 100644 --- a/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c +++ b/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c @@ -1,3 +1,4 @@ +#ifdef __ppc__ /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998 Geoffrey Keating @@ -380,18 +381,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) extern void ffi_call_AIX(/*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, - void (*fn)(), - void (*fn2)()); + void (*fn)(void), + void (*fn2)(extended_cif *, unsigned *const)); extern void ffi_call_DARWIN(/*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, - void (*fn)(), - void (*fn2)()); + void (*fn)(void), + void (*fn2)(extended_cif *, unsigned *const)); /*@=declundef@*/ /*@=exportheader@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, - void (*fn)(), + void (*fn)(void), /*@out@*/ void *rvalue, /*@dependent@*/ void **avalue) { @@ -767,3 +768,4 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, /* Tell ffi_closure_ASM to perform return type promotions. */ return cif->rtype->type; } +#endif diff --git a/Modules/_ctypes/libffi/src/prep_cif.c b/Modules/_ctypes/libffi/src/prep_cif.c index 0faa5dd..2db65ce 100644 --- a/Modules/_ctypes/libffi/src/prep_cif.c +++ b/Modules/_ctypes/libffi/src/prep_cif.c @@ -55,11 +55,29 @@ static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg) /* Perform a sanity check on the argument type */ FFI_ASSERT_VALID_TYPE(*ptr); +#ifdef POWERPC_DARWIN + { + int curalign; + + curalign = (*ptr)->alignment; + if (ptr != &(arg->elements[0])) { + if (curalign > 4 && curalign != 16) { + curalign = 4; + } + } + arg->size = ALIGN(arg->size, curalign); + arg->size += (*ptr)->size; + + arg->alignment = (arg->alignment > curalign) ? + arg->alignment : curalign; + } +#else arg->size = ALIGN(arg->size, (*ptr)->alignment); arg->size += (*ptr)->size; arg->alignment = (arg->alignment > (*ptr)->alignment) ? arg->alignment : (*ptr)->alignment; +#endif ptr++; } @@ -89,6 +107,19 @@ static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg) /* Perform machine independent ffi_cif preparation, then call machine dependent routine. */ +#ifdef X86_DARWIN +static inline int struct_on_stack(int size) +{ + if (size > 8) return 1; + /* This is not what the ABI says, but is what is really implemented */ + switch (size) { + case 1: case 2: case 4: case 8: return 0; + } + return 1; +} +#endif + + ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, ffi_abi abi, unsigned int nargs, /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, @@ -124,6 +155,10 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, #ifdef SPARC && (cif->abi != FFI_V9 || cif->rtype->size > 32) #endif +#ifdef X86_DARWIN + + && (struct_on_stack(cif->rtype->size)) +#endif ) bytes = STACK_ARG_SIZE(sizeof(void*)); #endif @@ -139,7 +174,16 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, check after the initialization. */ FFI_ASSERT_VALID_TYPE(*ptr); -#if !defined __x86_64__ && !defined S390 && !defined PA +#if defined(X86_DARWIN) + { + int align = (*ptr)->alignment; + if (align > 4) align = 4; + if ((align - 1) & bytes) + bytes = ALIGN(bytes, align); + bytes += STACK_ARG_SIZE((*ptr)->size); + } + +#elif !defined __x86_64__ && !defined S390 && !defined PA #ifdef SPARC if (((*ptr)->type == FFI_TYPE_STRUCT && ((*ptr)->size > 16 || cif->abi != FFI_V9)) diff --git a/Modules/_ctypes/libffi/src/x86/darwin.S b/Modules/_ctypes/libffi/src/x86/darwin.S new file mode 100644 index 0000000..c5e55b5 --- /dev/null +++ b/Modules/_ctypes/libffi/src/x86/darwin.S @@ -0,0 +1,195 @@ +#ifdef __i386__ +/* ----------------------------------------------------------------------- + darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. + + X86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +/* + * This file is based on sysv.S and then hacked up by Ronald who hasn't done + * assembly programming in 8 years. + */ + +#ifndef __x86_64__ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> + +.text + +.globl _ffi_prep_args + +.align 4 +.globl _ffi_call_SYSV + +_ffi_call_SYSV: +.LFB1: + pushl %ebp +.LCFI0: + movl %esp,%ebp +.LCFI1: + /* Make room for all of the new args. */ + movl 16(%ebp),%ecx + subl %ecx,%esp + + movl %esp,%eax + + /* Place all of the ffi_prep_args in position */ + pushl 12(%ebp) + pushl %eax + call *8(%ebp) + + /* Return stack to previous state and call the function */ + addl $8,%esp + + call *28(%ebp) + + /* Remove the space we pushed for the args */ + movl 16(%ebp),%ecx + addl %ecx,%esp + + /* Load %ecx with the return type code */ + movl 20(%ebp),%ecx + + /* If the return value pointer is NULL, assume no return value. */ + cmpl $0,24(%ebp) + jne retint + + /* Even if there is no space for the return value, we are + obliged to handle floating-point values. */ + cmpl $FFI_TYPE_FLOAT,%ecx + jne noretval + fstp %st(0) + + jmp epilogue + +retint: + cmpl $FFI_TYPE_INT,%ecx + jne retfloat + /* Load %ecx with the pointer to storage for the return value */ + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + jmp epilogue + +retfloat: + cmpl $FFI_TYPE_FLOAT,%ecx + jne retdouble + /* Load %ecx with the pointer to storage for the return value */ + movl 24(%ebp),%ecx + fstps (%ecx) + jmp epilogue + +retdouble: + cmpl $FFI_TYPE_DOUBLE,%ecx + jne retlongdouble + /* Load %ecx with the pointer to storage for the return value */ + movl 24(%ebp),%ecx + fstpl (%ecx) + jmp epilogue + +retlongdouble: + cmpl $FFI_TYPE_LONGDOUBLE,%ecx + jne retint64 + /* Load %ecx with the pointer to storage for the return value */ + movl 24(%ebp),%ecx + fstpt (%ecx) + jmp epilogue + +retint64: + cmpl $FFI_TYPE_SINT64,%ecx + jne retstruct + /* Load %ecx with the pointer to storage for the return value */ + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + movl %edx,4(%ecx) + +retstruct: + /* Nothing to do! */ + +noretval: +epilogue: + movl %ebp,%esp + popl %ebp + ret +.LFE1: +.ffi_call_SYSV_end: +#if 0 + .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV +#endif + +#if 0 + .section .eh_frame,EH_FRAME_FLAGS,@progbits +.Lframe1: + .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ +.LSCIE1: + .long 0x0 /* CIE Identifier Tag */ + .byte 0x1 /* CIE Version */ +#ifdef __PIC__ + .ascii "zR\0" /* CIE Augmentation */ +#else + .ascii "\0" /* CIE Augmentation */ +#endif + .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ + .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ + .byte 0x8 /* CIE RA Column */ +#ifdef __PIC__ + .byte 0x1 /* .uleb128 0x1; Augmentation size */ + .byte 0x1b /* FDE Encoding (pcrel sdata4) */ +#endif + .byte 0xc /* DW_CFA_def_cfa */ + .byte 0x4 /* .uleb128 0x4 */ + .byte 0x4 /* .uleb128 0x4 */ + .byte 0x88 /* DW_CFA_offset, column 0x8 */ + .byte 0x1 /* .uleb128 0x1 */ + .align 4 +.LECIE1: +.LSFDE1: + .long .LEFDE1-.LASFDE1 /* FDE Length */ +.LASFDE1: + .long .LASFDE1-.Lframe1 /* FDE CIE offset */ +#ifdef __PIC__ + .long .LFB1-. /* FDE initial location */ +#else + .long .LFB1 /* FDE initial location */ +#endif + .long .LFE1-.LFB1 /* FDE address range */ +#ifdef __PIC__ + .byte 0x0 /* .uleb128 0x0; Augmentation size */ +#endif + .byte 0x4 /* DW_CFA_advance_loc4 */ + .long .LCFI0-.LFB1 + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte 0x8 /* .uleb128 0x8 */ + .byte 0x85 /* DW_CFA_offset, column 0x5 */ + .byte 0x2 /* .uleb128 0x2 */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .long .LCFI1-.LCFI0 + .byte 0xd /* DW_CFA_def_cfa_register */ + .byte 0x5 /* .uleb128 0x5 */ + .align 4 +.LEFDE1: +#endif + +#endif /* ifndef __x86_64__ */ + +#endif /* defined __i386__ */ diff --git a/Modules/_ctypes/libffi/src/x86/ffi_darwin.c b/Modules/_ctypes/libffi/src/x86/ffi_darwin.c new file mode 100644 index 0000000..4f82b3a --- /dev/null +++ b/Modules/_ctypes/libffi/src/x86/ffi_darwin.c @@ -0,0 +1,610 @@ +# ifdef __i386__ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. + Copyright (c) 2002 Ranjit Mathew + Copyright (c) 2002 Bo Thorsen + Copyright (c) 2002 Roger Sayle + + x86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#ifndef __x86_64__ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +/*@-exportheader@*/ +void ffi_prep_args(char *stack, extended_cif *ecif); + +static inline int retval_on_stack(ffi_type* tp) +{ + if (tp->type == FFI_TYPE_STRUCT) { + int sz = tp->size; + if (sz > 8) { + return 1; + } + switch (sz) { + case 1: case 2: case 4: case 8: return 0; + default: return 1; + } + } + return 0; +} + + +void ffi_prep_args(char *stack, extended_cif *ecif) +/*@=exportheader@*/ +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if (retval_on_stack(ecif->cif->rtype)) { + *(void **) argp = ecif->rvalue; + argp += 4; + } + + + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + i != 0; + i--, p_arg++) + { + size_t z; + + /* Align if necessary */ + if ((sizeof(int) - 1) & (unsigned) argp) + argp = (char *) ALIGN(argp, sizeof(int)); + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_SINT32: + *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv); + break; + + case FFI_TYPE_UINT32: + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + break; + + default: + FFI_ASSERT(0); + } + } + else + { + memcpy(argp, *p_argv, z); + } + p_argv++; + argp += z; + } + + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Set the return type flag */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: +#if !defined(X86_WIN32) + case FFI_TYPE_STRUCT: +#endif + case FFI_TYPE_SINT64: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + cif->flags = (unsigned) cif->rtype->type; + break; + + case FFI_TYPE_UINT64: + cif->flags = FFI_TYPE_SINT64; + break; + +#if defined X86_WIN32 + + case FFI_TYPE_STRUCT: + if (cif->rtype->size == 1) + { + cif->flags = FFI_TYPE_SINT8; /* same as char size */ + } + else if (cif->rtype->size == 2) + { + cif->flags = FFI_TYPE_SINT16; /* same as short size */ + } + else if (cif->rtype->size == 4) + { + cif->flags = FFI_TYPE_INT; /* same as int type */ + } + else if (cif->rtype->size == 8) + { + cif->flags = FFI_TYPE_SINT64; /* same as int64 type */ + } + else + { + cif->flags = FFI_TYPE_STRUCT; + } + break; +#endif + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + /* Darwin: The stack needs to be aligned to a multiple of 16 bytes */ +#if 0 + cif->bytes = (cif->bytes + 15) & ~0xF; +#endif + + return FFI_OK; +} + +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_SYSV(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)(void)); +/*@=declundef@*/ +/*@=exportheader@*/ + +#ifdef X86_WIN32 +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)(void)); +/*@=declundef@*/ +/*@=exportheader@*/ +#endif /* X86_WIN32 */ + +void ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue) +{ + extended_cif ecif; + int flags; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && retval_on_stack(cif->rtype)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + flags = cif->flags; + if (flags == FFI_TYPE_STRUCT) { + if (cif->rtype->size == 8) { + flags = FFI_TYPE_SINT64; + } else if (cif->rtype->size == 4) { + flags = FFI_TYPE_INT; + } else if (cif->rtype->size == 2) { + flags = FFI_TYPE_INT; + } else if (cif->rtype->size == 1) { + flags = FFI_TYPE_INT; + } + } + + + switch (cif->abi) + { + case FFI_SYSV: + /*@-usedef@*/ + /* To avoid changing the assembly code make sure the size of the argument + * block is a multiple of 16. Then add 8 to compensate for local variables + * in ffi_call_SYSV. + */ + ffi_call_SYSV(ffi_prep_args, &ecif, ALIGN(cif->bytes, 16) +8, + flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#ifdef X86_WIN32 + case FFI_STDCALL: + /*@-usedef@*/ + ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#endif /* X86_WIN32 */ + default: + FFI_ASSERT(0); + break; + } +} + + +/** private members **/ + +static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, + void** args, ffi_cif* cif); +static void ffi_closure_SYSV (ffi_closure *) + __attribute__ ((regparm(1))); +#if !FFI_NO_RAW_API +static void ffi_closure_raw_SYSV (ffi_raw_closure *) + __attribute__ ((regparm(1))); +#endif + +/* This function is jumped to by the trampoline */ + +static void +ffi_closure_SYSV (closure) + ffi_closure *closure; +{ + // this is our return value storage + long double res; + + // our various things... + ffi_cif *cif; + void **arg_area; + unsigned short rtype; + void *resp = (void*)&res; + void *args = __builtin_dwarf_cfa (); + + cif = closure->cif; + arg_area = (void**) alloca (cif->nargs * sizeof (void*)); + + /* this call will initialize ARG_AREA, such that each + * element in that array points to the corresponding + * value on the stack; and if the function returns + * a structure, it will re-set RESP to point to the + * structure return address. */ + + ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif); + + (closure->fun) (cif, resp, arg_area, closure->user_data); + + rtype = cif->flags; + + if (!retval_on_stack(cif->rtype) && cif->flags == FFI_TYPE_STRUCT) { + if (cif->rtype->size == 8) { + rtype = FFI_TYPE_SINT64; + } else { + rtype = FFI_TYPE_INT; + } + } + + /* now, do a generic return based on the value of rtype */ + if (rtype == FFI_TYPE_INT) + { + asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); + } + else if (rtype == FFI_TYPE_FLOAT) + { + asm ("flds (%0)" : : "r" (resp) : "st" ); + } + else if (rtype == FFI_TYPE_DOUBLE) + { + asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_LONGDOUBLE) + { + asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_SINT64) + { + asm ("movl 0(%0),%%eax;" + "movl 4(%0),%%edx" + : : "r"(resp) + : "eax", "edx"); + } +#ifdef X86_WIN32 + else if (rtype == FFI_TYPE_SINT8) /* 1-byte struct */ + { + asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax"); + } + else if (rtype == FFI_TYPE_SINT16) /* 2-bytes struct */ + { + asm ("movswl (%0),%%eax" : : "r" (resp) : "eax"); + } +#endif +} + +/*@-exportheader@*/ +static void +ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +/*@=exportheader@*/ +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if (retval_on_stack(cif->rtype)) { + *rvalue = *(void **) argp; + argp += 4; + } + + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + + /* Align if necessary */ + if ((sizeof(int) - 1) & (unsigned) argp) { + argp = (char *) ALIGN(argp, sizeof(int)); + } + + z = (*p_arg)->size; + + /* because we're little endian, this is what it turns into. */ + + *p_argv = (void*) argp; + + p_argv++; + argp += z; + } + + return; +} + +/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */ + +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \ + *(unsigned char*) &__tramp[0] = 0xb8; \ + *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ + *(unsigned char *) &__tramp[5] = 0xe9; \ + *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ + }) + + +/* the cif must already be prep'ed */ + +ffi_status +ffi_prep_closure (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data) +{ + FFI_ASSERT (cif->abi == FFI_SYSV); + + FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ + &ffi_closure_SYSV, \ + (void*)closure); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + +/* ------- Native raw API support -------------------------------- */ + +#if !FFI_NO_RAW_API + +static void +ffi_closure_raw_SYSV (closure) + ffi_raw_closure *closure; +{ + // this is our return value storage + long double res; + + // our various things... + ffi_raw *raw_args; + ffi_cif *cif; + unsigned short rtype; + void *resp = (void*)&res; + + /* get the cif */ + cif = closure->cif; + + /* the SYSV/X86 abi matches the RAW API exactly, well.. almost */ + raw_args = (ffi_raw*) __builtin_dwarf_cfa (); + + (closure->fun) (cif, resp, raw_args, closure->user_data); + + rtype = cif->flags; + + /* now, do a generic return based on the value of rtype */ + if (rtype == FFI_TYPE_INT) + { + asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); + } + else if (rtype == FFI_TYPE_FLOAT) + { + asm ("flds (%0)" : : "r" (resp) : "st" ); + } + else if (rtype == FFI_TYPE_DOUBLE) + { + asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_LONGDOUBLE) + { + asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_SINT64) + { + asm ("movl 0(%0),%%eax; movl 4(%0),%%edx" + : : "r"(resp) + : "eax", "edx"); + } +} + + + + +ffi_status +ffi_prep_raw_closure (ffi_raw_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data) +{ + int i; + + FFI_ASSERT (cif->abi == FFI_SYSV); + + // we currently don't support certain kinds of arguments for raw + // closures. This should be implemented by a separate assembly language + // routine, since it would require argument processing, something we + // don't do now for performance. + + for (i = cif->nargs-1; i >= 0; i--) + { + FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT); + FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); + } + + + FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, + (void*)closure); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + +static void +ffi_prep_args_raw(char *stack, extended_cif *ecif) +{ + memcpy (stack, ecif->avalue, ecif->cif->bytes); +} + +/* we borrow this routine from libffi (it must be changed, though, to + * actually call the function passed in the first argument. as of + * libffi-1.20, this is not the case.) + */ + +extern void +ffi_call_SYSV(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); + +#ifdef X86_WIN32 +extern void +ffi_call_STDCALL(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +#endif /* X86_WIN32 */ + +void +ffi_raw_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ ffi_raw *fake_avalue) +{ + extended_cif ecif; + void **avalue = (void **)fake_avalue; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && retval_on_stack(cif->rtype)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + + switch (cif->abi) + { + case FFI_SYSV: + /*@-usedef@*/ + ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#ifdef X86_WIN32 + case FFI_STDCALL: + /*@-usedef@*/ + ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#endif /* X86_WIN32 */ + default: + FFI_ASSERT(0); + break; + } +} + +#endif + +#endif /* __x86_64__ */ + +#endif /* __i386__ */ diff --git a/Modules/_ctypes/libffi/src/x86/ffitarget.h b/Modules/_ctypes/libffi/src/x86/ffitarget.h index 9500f40..8b20d3c 100644 --- a/Modules/_ctypes/libffi/src/x86/ffitarget.h +++ b/Modules/_ctypes/libffi/src/x86/ffitarget.h @@ -51,7 +51,7 @@ typedef enum ffi_abi { #endif /* ---- Intel x86 and AMD x86-64 - */ -#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) +#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) FFI_SYSV, FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ #ifdef __i386__ diff --git a/Modules/_ctypes/libffi_msvc/ffi.c b/Modules/_ctypes/libffi_msvc/ffi.c index 5c49b39..e5600b2 100644 --- a/Modules/_ctypes/libffi_msvc/ffi.c +++ b/Modules/_ctypes/libffi_msvc/ffi.c @@ -26,8 +26,6 @@ OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#ifndef __x86_64__ - #include <ffi.h> #include <ffi_common.h> @@ -143,11 +141,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /*@-declundef@*/ /*@-exportheader@*/ -#ifdef _MSC_VER extern int -#else -extern void -#endif ffi_call_SYSV(void (*)(char *, extended_cif *), /*@out@*/ extended_cif *, unsigned, unsigned, @@ -156,14 +150,9 @@ ffi_call_SYSV(void (*)(char *, extended_cif *), /*@=declundef@*/ /*@=exportheader@*/ -#if defined(X86_WIN32) || defined(_MSC_VER) /*@-declundef@*/ /*@-exportheader@*/ -#ifdef _MSC_VER extern int -#else -extern void -#endif ffi_call_STDCALL(void (*)(char *, extended_cif *), /*@out@*/ extended_cif *, unsigned, unsigned, @@ -171,13 +160,8 @@ ffi_call_STDCALL(void (*)(char *, extended_cif *), void (*fn)()); /*@=declundef@*/ /*@=exportheader@*/ -#endif /* X86_WIN32 || _MSC_VER*/ -#ifdef _MSC_VER int -#else -void -#endif ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, @@ -206,24 +190,18 @@ ffi_call(/*@dependent@*/ ffi_cif *cif, { case FFI_SYSV: /*@-usedef@*/ -#ifdef _MSC_VER - return -#endif - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); + return ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; -#if defined(X86_WIN32) || defined(_MSC_VER) + case FFI_STDCALL: /*@-usedef@*/ -#ifdef _MSC_VER - return -#endif - ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); + return ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; -#endif /* X86_WIN32 */ + default: FFI_ASSERT(0); break; @@ -236,23 +214,10 @@ ffi_call(/*@dependent@*/ ffi_cif *cif, static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, void** args, ffi_cif* cif); -#ifndef _MSC_VER -static void ffi_closure_SYSV (ffi_closure *) - __attribute__ ((regparm(1))); -static void ffi_closure_raw_SYSV (ffi_raw_closure *) - __attribute__ ((regparm(1))); -#endif - /* This function is jumped to by the trampoline */ -#ifdef _MSC_VER static void __fastcall ffi_closure_SYSV (ffi_closure *closure, int *argp) -#else -static void -ffi_closure_SYSV (closure) - ffi_closure *closure; -#endif { // this is our return value storage long double res; @@ -262,11 +227,11 @@ ffi_closure_SYSV (closure) void **arg_area; unsigned short rtype; void *resp = (void*)&res; -#ifdef _MSC_VER +//#ifdef _MSC_VER void *args = &argp[1]; -#else - void *args = __builtin_dwarf_cfa (); -#endif +//#else +// void *args = __builtin_dwarf_cfa (); +//#endif cif = closure->cif; arg_area = (void**) alloca (cif->nargs * sizeof (void*)); @@ -390,7 +355,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, /* MOV EDX, ESP is 0x8b 0xd4 */ -#ifdef _MSC_VER +//#ifdef _MSC_VER #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \ { unsigned char *__tramp = (unsigned char*)(TRAMP); \ @@ -407,18 +372,18 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, *(unsigned short*) &__tramp[13] = BYTES; \ } -#else -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \ -({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \ - *(unsigned char*) &__tramp[0] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[5] = 0xe9; \ - *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ - }) -#endif +//#else +//#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \ +//({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ +// unsigned int __fun = (unsigned int)(FUN); \ +// unsigned int __ctx = (unsigned int)(CTX); \ +// unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \ +// *(unsigned char*) &__tramp[0] = 0xb8; \ +// *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ +// *(unsigned char *) &__tramp[5] = 0xe9; \ +// *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ +// }) +//#endif /* the cif must already be prep'ed */ @@ -433,10 +398,8 @@ ffi_prep_closure (ffi_closure* closure, if (cif->abi == FFI_SYSV) bytes = 0; -#ifdef _MSC_VER else if (cif->abi == FFI_STDCALL) bytes = cif->bytes; -#endif else return FFI_BAD_ABI; @@ -450,5 +413,3 @@ ffi_prep_closure (ffi_closure* closure, return FFI_OK; } - -#endif /* __x86_64__ */ diff --git a/Modules/_ctypes/libffi_msvc/ffi.h b/Modules/_ctypes/libffi_msvc/ffi.h index b9d31fd..203142d 100644 --- a/Modules/_ctypes/libffi_msvc/ffi.h +++ b/Modules/_ctypes/libffi_msvc/ffi.h @@ -272,11 +272,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, /*@dependent@*/ ffi_type **atypes); -#ifdef _MSC_VER int -#else -void -#endif ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, diff --git a/Modules/_ctypes/libffi_msvc/ffi_common.h b/Modules/_ctypes/libffi_msvc/ffi_common.h index 1b948d5..43fb83b 100644 --- a/Modules/_ctypes/libffi_msvc/ffi_common.h +++ b/Modules/_ctypes/libffi_msvc/ffi_common.h @@ -13,24 +13,7 @@ extern "C" { #endif #include <fficonfig.h> - -/* Do not move this. Some versions of AIX are very picky about where - this is positioned. */ -#ifdef __GNUC__ -# define alloca __builtin_alloca -#else -# if HAVE_ALLOCA_H -# include <alloca.h> -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -# endif -# endif -# endif -#endif +#include <malloc.h> /* Check for the existence of memcpy. */ #if STDC_HEADERS diff --git a/Modules/_ctypes/libffi_msvc/ffitarget.h b/Modules/_ctypes/libffi_msvc/ffitarget.h index c9d95bc..57d275b 100644 --- a/Modules/_ctypes/libffi_msvc/ffitarget.h +++ b/Modules/_ctypes/libffi_msvc/ffitarget.h @@ -43,23 +43,21 @@ typedef enum ffi_abi { FFI_FIRST_ABI = 0, /* ---- Intel x86 Win32 ---------- */ -#if defined(X86_WIN32) || defined(_MSC_VER) FFI_SYSV, FFI_STDCALL, /* TODO: Add fastcall support for the sake of completeness */ FFI_DEFAULT_ABI = FFI_SYSV, -#endif /* ---- Intel x86 and AMD x86-64 - */ -#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) - FFI_SYSV, - FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ -#ifdef __i386__ - FFI_DEFAULT_ABI = FFI_SYSV, -#else - FFI_DEFAULT_ABI = FFI_UNIX64, -#endif -#endif +/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */ +/* FFI_SYSV, */ +/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */ +/* #ifdef __i386__ */ +/* FFI_DEFAULT_ABI = FFI_SYSV, */ +/* #else */ +/* FFI_DEFAULT_ABI = FFI_UNIX64, */ +/* #endif */ +/* #endif */ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; diff --git a/Modules/_ctypes/libffi_msvc/mingwin32.S b/Modules/_ctypes/libffi_msvc/mingwin32.S new file mode 100644 index 0000000..e71f2b2 --- /dev/null +++ b/Modules/_ctypes/libffi_msvc/mingwin32.S @@ -0,0 +1,228 @@ +/* ----------------------------------------------------------------------- + win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc. + Copyright (c) 2001 John Beniton + Copyright (c) 2002 Ranjit Mathew + + + X86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> + +.text + +.globl ffi_prep_args + + # This assumes we are using gas. + .balign 16 +.globl _ffi_call_SYSV + +_ffi_call_SYSV: + pushl %ebp + movl %esp,%ebp + + # Make room for all of the new args. + movl 16(%ebp),%ecx + subl %ecx,%esp + + movl %esp,%eax + + # Place all of the ffi_prep_args in position + pushl 12(%ebp) + pushl %eax + call *8(%ebp) + + # Return stack to previous state and call the function + addl $8,%esp + + # FIXME: Align the stack to a 128-bit boundary to avoid + # potential performance hits. + + call *28(%ebp) + + # Remove the space we pushed for the args + movl 16(%ebp),%ecx + addl %ecx,%esp + + # Load %ecx with the return type code + movl 20(%ebp),%ecx + + # If the return value pointer is NULL, assume no return value. + cmpl $0,24(%ebp) + jne retint + + # Even if there is no space for the return value, we are + # obliged to handle floating-point values. + cmpl $2,%ecx # Float_type + jne noretval + fstp %st(0) + + jmp epilogue + +retint: + cmpl $1,%ecx # Int_type + jne retfloat + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + jmp epilogue + +retfloat: + cmpl $2,%ecx # Float_type + jne retdouble + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstps (%ecx) + jmp epilogue + +retdouble: + cmpl $3,%ecx # Double_type + jne retlongdouble + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstpl (%ecx) + jmp epilogue + +retlongdouble: + cmpl $4,%ecx # Longdouble_type + jne retint64 + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstpt (%ecx) + jmp epilogue + +retint64: + cmpl $12,%ecx # SINT64_type + jne retstruct + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + movl %edx,4(%ecx) + +retstruct: + # Nothing to do! + +noretval: +epilogue: + movl %ebp,%esp + popl %ebp + ret + +.ffi_call_SYSV_end: + + # This assumes we are using gas. + .balign 16 +.globl _ffi_call_STDCALL + +_ffi_call_STDCALL: + pushl %ebp + movl %esp,%ebp + + # Make room for all of the new args. + movl 16(%ebp),%ecx + subl %ecx,%esp + + movl %esp,%eax + + # Place all of the ffi_prep_args in position + pushl 12(%ebp) + pushl %eax + call *8(%ebp) + + # Return stack to previous state and call the function + addl $8,%esp + + # FIXME: Align the stack to a 128-bit boundary to avoid + # potential performance hits. + + call *28(%ebp) + + # stdcall functions pop arguments off the stack themselves + + # Load %ecx with the return type code + movl 20(%ebp),%ecx + + # If the return value pointer is NULL, assume no return value. + cmpl $0,24(%ebp) + jne sc_retint + + # Even if there is no space for the return value, we are + # obliged to handle floating-point values. + cmpl $2,%ecx # Float_type + jne sc_noretval + fstp %st(0) + + jmp sc_epilogue + +sc_retint: + cmpl $1,%ecx # Int_type + jne sc_retfloat + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + jmp sc_epilogue + +sc_retfloat: + cmpl $2,%ecx # Float_type + jne sc_retdouble + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstps (%ecx) + jmp sc_epilogue + +sc_retdouble: + cmpl $2,%ecx # Double_type + jne sc_retlongdouble + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstpl (%ecx) + jmp sc_epilogue + +sc_retlongdouble: + cmpl $4,%ecx # Longdouble_type + jne sc_retint64 + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstpt (%ecx) + jmp sc_epilogue + +sc_retint64: + cmpl $12,%ecx # SINT64_Type + jne sc_retstruct + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + movl %edx,4(%ecx) + +sc_retstruct: + # Nothing to do! + +sc_noretval: +sc_epilogue: + movl %ebp,%esp + popl %ebp + ret + +.ffi_call_STDCALL_end: + diff --git a/Modules/_ctypes/libffi_msvc/prep_cif.c b/Modules/_ctypes/libffi_msvc/prep_cif.c index 9edce2f..2650fa0 100644 --- a/Modules/_ctypes/libffi_msvc/prep_cif.c +++ b/Modules/_ctypes/libffi_msvc/prep_cif.c @@ -147,7 +147,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, else #endif { -#ifndef _MSC_VER +#if !defined(_MSC_VER) && !defined(__MINGW32__) /* Don't know if this is a libffi bug or not. At least on Windows with MSVC, function call parameters are *not* aligned in the same way as structure fields are, they are diff --git a/Modules/_ctypes/libffi_msvc/win32.S b/Modules/_ctypes/libffi_msvc/win32.S index 40743af..cc82ab9 100644 --- a/Modules/_ctypes/libffi_msvc/win32.S +++ b/Modules/_ctypes/libffi_msvc/win32.S @@ -41,7 +41,11 @@ _ffi_call_SYSV: pushl %ebp movl %esp,%ebp - + + #THe: save previous %esi, and store the current stack pointer in %esi + pushl %esi + movl %esp,%esi + # Make room for all of the new args. movl 16(%ebp),%ecx subl %ecx,%esp @@ -64,7 +68,9 @@ _ffi_call_SYSV: # Remove the space we pushed for the args movl 16(%ebp),%ecx addl %ecx,%esp - + + sub %esp,%esi # calculate stack pointer difference + # Load %ecx with the return type code movl 20(%ebp),%ecx @@ -125,6 +131,8 @@ retstruct: noretval: epilogue: + movl %esi,%eax # return the stack pointer detlta in %eax + popl %esi # restore previous %esi movl %ebp,%esp popl %ebp ret @@ -139,6 +147,10 @@ _ffi_call_STDCALL: pushl %ebp movl %esp,%ebp + #THe: save previous %esi, and store the current stack pointer in %esi + pushl %esi + movl %esp,%esi + # Make room for all of the new args. movl 16(%ebp),%ecx subl %ecx,%esp @@ -158,6 +170,8 @@ _ffi_call_STDCALL: call *28(%ebp) + sub %esp,%esi # difference in stack + # stdcall functions pop arguments off the stack themselves # Load %ecx with the return type code @@ -220,6 +234,8 @@ sc_retstruct: sc_noretval: sc_epilogue: + movl %esi,%eax # return the stack difference + popl %esi # restore previous %esi value movl %ebp,%esp popl %ebp ret diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 7e36ea3..871aa18 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -327,8 +327,10 @@ element_new(PyObject* tag, PyObject* attrib) if (attrib != Py_None) { - if (element_new_extra(self, attrib) < 0) + if (element_new_extra(self, attrib) < 0) { + PyObject_Del(self); return NULL; + } self->extra->length = 0; self->extra->allocated = STATIC_CHILDREN; diff --git a/Modules/_hotshot.c b/Modules/_hotshot.c index 2ee4eb9..3ad0a9e 100644 --- a/Modules/_hotshot.c +++ b/Modules/_hotshot.c @@ -1420,7 +1420,7 @@ write_header(ProfilerObject *self) char *buffer; char cwdbuffer[PATH_MAX]; PyObject *temp; - int i, len; + Py_ssize_t i, len; buffer = get_version_string(); if (buffer == NULL) { diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index e3d1e7f..58beb5c 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -12,11 +12,14 @@ This software comes with no warranty. Use at your own risk. #include "Python.h" #include <stdio.h> -#include <errno.h> #include <locale.h> #include <string.h> #include <ctype.h> +#ifndef DONT_HAVE_ERRNO_H +#include <errno.h> +#endif + #ifdef HAVE_LANGINFO_H #include <langinfo.h> #endif diff --git a/Modules/_sqlite/adapters.c b/Modules/_sqlite/adapters.c deleted file mode 100644 index e6fde03..0000000 --- a/Modules/_sqlite/adapters.c +++ /dev/null @@ -1,40 +0,0 @@ -/* adapters.c - default adapters - * - * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de> - * - * This file is part of pysqlite. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include "util.h" -#include "module.h" -#include "adapters.h" - -/* dummy, will be implemented in a later version */ - -PyObject* adapt_date(PyObject* self, PyObject* args, PyObject* kwargs) -{ - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* adapt_datetime(PyObject* self, PyObject* args, PyObject* kwargs) -{ - Py_INCREF(Py_None); - return Py_None; -} diff --git a/Modules/_sqlite/adapters.h b/Modules/_sqlite/adapters.h deleted file mode 100644 index d2e8479..0000000 --- a/Modules/_sqlite/adapters.h +++ /dev/null @@ -1,33 +0,0 @@ -/* adapters.h - default adapters - * - * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de> - * - * This file is part of pysqlite. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PYSQLITE_ADAPTERS_H -#define PYSQLITE_ADAPTERS_H -#include "Python.h" -#include "pythread.h" -#include "sqlite3.h" - -PyObject* adapt_date(PyObject* self, PyObject* args, PyObject* kwargs); -PyObject* adapt_datetime(PyObject* self, PyObject* args, PyObject* kwargs); - -#endif diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index d102e97..6962695 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -22,6 +22,7 @@ */ #include "cache.h" +#include <limits.h> /* only used internally */ Node* new_node(PyObject* key, PyObject* data) @@ -60,11 +61,11 @@ int cache_init(Cache* self, PyObject* args, PyObject* kwargs) self->factory = NULL; - if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) - { - return -1; + if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) { + return -1; } + /* minimum cache size is 5 entries */ if (size < 5) { size = 5; } @@ -95,6 +96,7 @@ void cache_dealloc(Cache* self) return; } + /* iterate over all nodes and deallocate them */ node = self->first; while (node) { delete_node = node; @@ -119,7 +121,14 @@ PyObject* cache_get(Cache* self, PyObject* args) node = (Node*)PyDict_GetItem(self->mapping, key); if (node) { - node->count++; + /* an entry for this key already exists in the cache */ + + /* increase usage counter of the node found */ + if (node->count < LONG_MAX) { + node->count++; + } + + /* if necessary, reorder entries in the cache by swapping positions */ if (node->prev && node->count > node->prev->count) { ptr = node->prev; @@ -149,6 +158,10 @@ PyObject* cache_get(Cache* self, PyObject* args) ptr->prev = node; } } else { + /* There is no entry for this key in the cache, yet. We'll insert a new + * entry in the cache, and make space if necessary by throwing the + * least used item out of the cache. */ + if (PyDict_Size(self->mapping) == self->size) { if (self->last) { node = self->last; @@ -253,7 +266,7 @@ PyObject* cache_display(Cache* self, PyObject* args) static PyMethodDef cache_methods[] = { {"get", (PyCFunction)cache_get, METH_O, - PyDoc_STR("Gets an entry from the cache.")}, + PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")}, {"display", (PyCFunction)cache_display, METH_NOARGS, PyDoc_STR("For debugging only.")}, {NULL, NULL} diff --git a/Modules/_sqlite/cache.h b/Modules/_sqlite/cache.h index 5cc16f3..1f13907 100644 --- a/Modules/_sqlite/cache.h +++ b/Modules/_sqlite/cache.h @@ -1,6 +1,6 @@ /* cache.h - definitions for the LRU cache * - * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de> + * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de> * * This file is part of pysqlite. * @@ -25,6 +25,10 @@ #define PYSQLITE_CACHE_H #include "Python.h" +/* The LRU cache is implemented as a combination of a doubly-linked with a + * dictionary. The list items are of type 'Node' and the dictionary has the + * nodes as values. */ + typedef struct _Node { PyObject_HEAD @@ -39,10 +43,18 @@ typedef struct { PyObject_HEAD int size; + + /* a dictionary mapping keys to Node entries */ PyObject* mapping; + + /* the factory callable */ PyObject* factory; + Node* first; Node* last; + + /* if set, decrement the factory function when the Cache is deallocated. + * this is almost always desirable, but not in the pysqlite context */ int decref_factory; } Cache; diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 78aad37..64e43eb 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -56,6 +56,7 @@ int connection_init(Connection* self, PyObject* args, PyObject* kwargs) self->begin_statement = NULL; self->statement_cache = NULL; + self->statements = NULL; Py_INCREF(Py_None); self->row_factory = Py_None; @@ -74,6 +75,9 @@ int connection_init(Connection* self, PyObject* args, PyObject* kwargs) if (!isolation_level) { isolation_level = PyString_FromString(""); + if (!isolation_level) { + return -1; + } } else { Py_INCREF(isolation_level); } @@ -86,6 +90,12 @@ int connection_init(Connection* self, PyObject* args, PyObject* kwargs) return -1; } + self->statements = PyList_New(0); + if (!self->statements) { + return -1; + } + self->created_statements = 0; + /* By default, the Cache class INCREFs the factory in its initializer, and * decrefs it in its deallocator method. Since this would create a circular * reference here, we're breaking it by decrementing self, and telling the @@ -126,6 +136,7 @@ int connection_init(Connection* self, PyObject* args, PyObject* kwargs) return 0; } +/* Empty the entire statement cache of this connection */ void flush_statement_cache(Connection* self) { Node* node; @@ -147,15 +158,16 @@ void flush_statement_cache(Connection* self) void reset_all_statements(Connection* self) { - Node* node; - Statement* statement; - - node = self->statement_cache->first; - - while (node) { - statement = (Statement*)(node->data); - (void)statement_reset(statement); - node = node->next; + int i; + PyObject* weakref; + PyObject* statement; + + for (i = 0; i < PyList_Size(self->statements); i++) { + weakref = PyList_GetItem(self->statements, i); + statement = PyWeakref_GetObject(weakref); + if (statement != Py_None) { + (void)statement_reset((Statement*)statement); + } } } @@ -178,6 +190,7 @@ void connection_dealloc(Connection* self) Py_XDECREF(self->row_factory); Py_XDECREF(self->text_factory); Py_XDECREF(self->collations); + Py_XDECREF(self->statements); self->ob_type->tp_free((PyObject*)self); } @@ -391,7 +404,7 @@ void _set_result(sqlite3_context* context, PyObject* py_val) Py_ssize_t buflen; PyObject* stringval; - if (PyErr_Occurred()) { + if ((!py_val) || PyErr_Occurred()) { /* Errors in callbacks are ignored, and we return NULL */ PyErr_Clear(); sqlite3_result_null(context); @@ -399,21 +412,23 @@ void _set_result(sqlite3_context* context, PyObject* py_val) sqlite3_result_null(context); } else if (PyInt_Check(py_val)) { longval = PyInt_AsLong(py_val); - /* TODO: investigate what to do with range overflows - long vs. long long */ sqlite3_result_int64(context, (PY_LONG_LONG)longval); } else if (PyFloat_Check(py_val)) { sqlite3_result_double(context, PyFloat_AsDouble(py_val)); } else if (PyBuffer_Check(py_val)) { if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) { PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); + } else { + sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT); } - sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT); } else if (PyString_Check(py_val)) { sqlite3_result_text(context, PyString_AsString(py_val), -1, SQLITE_TRANSIENT); } else if (PyUnicode_Check(py_val)) { stringval = PyUnicode_AsUTF8String(py_val); - sqlite3_result_text(context, PyString_AsString(stringval), -1, SQLITE_TRANSIENT); - Py_DECREF(stringval); + if (stringval) { + sqlite3_result_text(context, PyString_AsString(stringval), -1, SQLITE_TRANSIENT); + Py_DECREF(stringval); + } } else { /* TODO: raise error */ } @@ -450,6 +465,7 @@ PyObject* _build_py_params(sqlite3_context *context, int argc, sqlite3_value** a cur_py_value = PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL); /* TODO: have a way to show errors here */ if (!cur_py_value) { + PyErr_Clear(); Py_INCREF(Py_None); cur_py_value = Py_None; } @@ -458,10 +474,12 @@ PyObject* _build_py_params(sqlite3_context *context, int argc, sqlite3_value** a buflen = sqlite3_value_bytes(cur_value); cur_py_value = PyBuffer_New(buflen); if (!cur_py_value) { - /* TODO: error */ + break; } if (PyObject_AsWriteBuffer(cur_py_value, &raw_buffer, &buflen)) { - /* TODO: error */ + Py_DECREF(cur_py_value); + cur_py_value = NULL; + break; } memcpy(raw_buffer, sqlite3_value_blob(cur_value), buflen); break; @@ -470,6 +488,12 @@ PyObject* _build_py_params(sqlite3_context *context, int argc, sqlite3_value** a Py_INCREF(Py_None); cur_py_value = Py_None; } + + if (!cur_py_value) { + Py_DECREF(args); + return NULL; + } + PyTuple_SetItem(args, i, cur_py_value); } @@ -481,8 +505,7 @@ void _func_callback(sqlite3_context* context, int argc, sqlite3_value** argv) { PyObject* args; PyObject* py_func; - PyObject* py_retval; - + PyObject* py_retval = NULL; PyGILState_STATE threadstate; @@ -491,9 +514,10 @@ void _func_callback(sqlite3_context* context, int argc, sqlite3_value** argv) py_func = (PyObject*)sqlite3_user_data(context); args = _build_py_params(context, argc, argv); - - py_retval = PyObject_CallObject(py_func, args); - Py_DECREF(args); + if (args) { + py_retval = PyObject_CallObject(py_func, args); + Py_DECREF(args); + } _set_result(context, py_retval); Py_XDECREF(py_retval); @@ -504,10 +528,10 @@ void _func_callback(sqlite3_context* context, int argc, sqlite3_value** argv) static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** params) { PyObject* args; - PyObject* function_result; + PyObject* function_result = NULL; PyObject* aggregate_class; PyObject** aggregate_instance; - PyObject* stepmethod; + PyObject* stepmethod = NULL; PyGILState_STATE threadstate; @@ -520,44 +544,42 @@ static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** p if (*aggregate_instance == 0) { *aggregate_instance = PyObject_CallFunction(aggregate_class, ""); - if (PyErr_Occurred()) - { + if (PyErr_Occurred()) { PyErr_Clear(); *aggregate_instance = 0; - PyGILState_Release(threadstate); - return; + goto error; } } stepmethod = PyObject_GetAttrString(*aggregate_instance, "step"); - if (!stepmethod) - { - PyGILState_Release(threadstate); - return; + if (!stepmethod) { + goto error; } args = _build_py_params(context, argc, params); + if (!args) { + goto error; + } function_result = PyObject_CallObject(stepmethod, args); Py_DECREF(args); - Py_DECREF(stepmethod); - if (function_result == NULL) { + if (!function_result) { PyErr_Clear(); - } else { - Py_DECREF(function_result); } +error: + Py_XDECREF(stepmethod); + Py_XDECREF(function_result); + PyGILState_Release(threadstate); } void _final_callback(sqlite3_context* context) { - PyObject* args; - PyObject* function_result; + PyObject* function_result = NULL; PyObject** aggregate_instance; PyObject* aggregate_class; - PyObject* finalizemethod; PyGILState_STATE threadstate; @@ -570,35 +592,56 @@ void _final_callback(sqlite3_context* context) /* this branch is executed if there was an exception in the aggregate's * __init__ */ - PyGILState_Release(threadstate); - return; + goto error; } - finalizemethod = PyObject_GetAttrString(*aggregate_instance, "finalize"); - - if (!finalizemethod) { - /* - PyErr_SetString(ProgrammingError, "finalize method missing"); - goto error; - */ + function_result = PyObject_CallMethod(*aggregate_instance, "finalize", ""); + if (!function_result) { + PyErr_Clear(); Py_INCREF(Py_None); function_result = Py_None; - } else { - args = PyTuple_New(0); - if (!args) - return; - function_result = PyObject_CallObject(finalizemethod, args); - Py_DECREF(args); - Py_DECREF(finalizemethod); } _set_result(context, function_result); + +error: Py_XDECREF(*aggregate_instance); Py_XDECREF(function_result); PyGILState_Release(threadstate); } +void _drop_unused_statement_references(Connection* self) +{ + PyObject* new_list; + PyObject* weakref; + int i; + + /* we only need to do this once in a while */ + if (self->created_statements++ < 200) { + return; + } + + self->created_statements = 0; + + new_list = PyList_New(0); + if (!new_list) { + return; + } + + for (i = 0; i < PyList_Size(self->statements); i++) { + weakref = PyList_GetItem(self->statements, i); + if (weakref != Py_None) { + if (PyList_Append(new_list, weakref) != 0) { + Py_DECREF(new_list); + return; + } + } + } + + Py_DECREF(self->statements); + self->statements = new_list; +} PyObject* connection_create_function(Connection* self, PyObject* args, PyObject* kwargs) { @@ -617,10 +660,16 @@ PyObject* connection_create_function(Connection* self, PyObject* args, PyObject* rc = sqlite3_create_function(self->db, name, narg, SQLITE_UTF8, (void*)func, _func_callback, NULL, NULL); - PyDict_SetItem(self->function_pinboard, func, Py_None); + if (rc != SQLITE_OK) { + /* Workaround for SQLite bug: no error code or string is available here */ + PyErr_SetString(OperationalError, "Error creating function"); + return NULL; + } else { + PyDict_SetItem(self->function_pinboard, func, Py_None); - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; + } } PyObject* connection_create_aggregate(Connection* self, PyObject* args, PyObject* kwargs) @@ -639,7 +688,8 @@ PyObject* connection_create_aggregate(Connection* self, PyObject* args, PyObject rc = sqlite3_create_function(self->db, name, n_arg, SQLITE_UTF8, (void*)aggregate_class, 0, &_step_callback, &_final_callback); if (rc != SQLITE_OK) { - _seterror(self->db); + /* Workaround for SQLite bug: no error code or string is available here */ + PyErr_SetString(OperationalError, "Error creating aggregate"); return NULL; } else { PyDict_SetItem(self->function_pinboard, aggregate_class, Py_None); @@ -682,7 +732,6 @@ static PyObject* connection_get_total_changes(Connection* self, void* unused) static int connection_set_isolation_level(Connection* self, PyObject* isolation_level) { - PyObject* empty; PyObject* res; PyObject* begin_statement; @@ -697,15 +746,10 @@ static int connection_set_isolation_level(Connection* self, PyObject* isolation_ Py_INCREF(Py_None); self->isolation_level = Py_None; - empty = PyTuple_New(0); - if (!empty) { - return -1; - } - res = connection_commit(self, empty); + res = connection_commit(self, NULL); if (!res) { return -1; } - Py_DECREF(empty); Py_DECREF(res); self->inTransaction = 0; @@ -738,12 +782,15 @@ PyObject* connection_call(Connection* self, PyObject* args, PyObject* kwargs) { PyObject* sql; Statement* statement; + PyObject* weakref; int rc; if (!PyArg_ParseTuple(args, "O", &sql)) { return NULL; } + _drop_unused_statement_references(self); + statement = PyObject_New(Statement, &StatementType); if (!statement) { return NULL; @@ -762,8 +809,24 @@ PyObject* connection_call(Connection* self, PyObject* args, PyObject* kwargs) Py_DECREF(statement); statement = 0; + } else { + weakref = PyWeakref_NewRef((PyObject*)statement, NULL); + if (!weakref) { + Py_DECREF(statement); + statement = 0; + goto error; + } + + if (PyList_Append(self->statements, weakref) != 0) { + Py_DECREF(weakref); + statement = 0; + goto error; + } + + Py_DECREF(weakref); } +error: return (PyObject*)statement; } @@ -983,7 +1046,7 @@ finally: } static char connection_doc[] = -PyDoc_STR("<missing docstring>"); +PyDoc_STR("SQLite database connection object."); static PyGetSetDef connection_getset[] = { {"isolation_level", (getter)connection_get_isolation_level, (setter)connection_set_isolation_level}, @@ -1011,7 +1074,7 @@ static PyMethodDef connection_methods[] = { {"executescript", (PyCFunction)connection_executescript, METH_VARARGS, PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")}, {"create_collation", (PyCFunction)connection_create_collation, METH_VARARGS, - PyDoc_STR("Creates a collation function.")}, + PyDoc_STR("Creates a collation function. Non-standard.")}, {NULL, NULL} }; diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index faae6e4..8f4d36e 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -1,6 +1,6 @@ /* connection.h - definitions for the connection type * - * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de> + * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de> * * This file is part of pysqlite. * @@ -37,7 +37,12 @@ typedef struct PyObject_HEAD sqlite3* db; + /* 1 if we are currently within a transaction, i. e. if a BEGIN has been + * issued */ int inTransaction; + + /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a + * bitwise combination thereof makes sense */ int detect_types; /* the timeout value in seconds for database locks */ @@ -54,13 +59,31 @@ typedef struct * freed in connection destructor */ char* begin_statement; + /* 1 if a check should be performed for each API call if the connection is + * used from the same thread it was created in */ int check_same_thread; + + /* thread identification of the thread the connection was created in */ long thread_ident; Cache* statement_cache; + /* A list of weak references to statements used within this connection */ + PyObject* statements; + + /* a counter for how many statements were created in the connection. May be + * reset to 0 at certain intervals */ + int created_statements; + PyObject* row_factory; + /* Determines how bytestrings from SQLite are converted to Python objects: + * - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings + * - OptimizedUnicode: Like before, but for ASCII data, only PyStrings are created. + * - PyString_Type: PyStrings are created as-is. + * - Any custom callable: Any object returned from the callable called with the bytestring + * as single parameter. + */ PyObject* text_factory; /* remember references to functions/classes used in diff --git a/Modules/_sqlite/converters.c b/Modules/_sqlite/converters.c deleted file mode 100644 index 018063a..0000000 --- a/Modules/_sqlite/converters.c +++ /dev/null @@ -1,40 +0,0 @@ -/* converters.c - default converters - * - * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de> - * - * This file is part of pysqlite. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include "util.h" -#include "module.h" -#include "adapters.h" - -/* dummy, will be implemented in a later version */ - -PyObject* convert_date(PyObject* self, PyObject* args, PyObject* kwargs) -{ - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* convert_timestamp(PyObject* self, PyObject* args, PyObject* kwargs) -{ - Py_INCREF(Py_None); - return Py_None; -} diff --git a/Modules/_sqlite/converters.h b/Modules/_sqlite/converters.h deleted file mode 100644 index df3768a..0000000 --- a/Modules/_sqlite/converters.h +++ /dev/null @@ -1,33 +0,0 @@ -/* converters.h - default converters - * - * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de> - * - * This file is part of pysqlite. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PYSQLITE_CONVERTERS_H -#define PYSQLITE_CONVERTERS_H -#include "Python.h" -#include "pythread.h" -#include "sqlite3.h" - -PyObject* convert_date(PyObject* self, PyObject* args, PyObject* kwargs); -PyObject* convert_timestamp(PyObject* self, PyObject* args, PyObject* kwargs); - -#endif diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index c6b8c77..6ee8bea 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -27,8 +27,12 @@ #include "sqlitecompat.h" /* used to decide wether to call PyInt_FromLong or PyLong_FromLongLong */ +#ifndef INT32_MIN #define INT32_MIN (-2147483647 - 1) +#endif +#ifndef INT32_MAX #define INT32_MAX 2147483647 +#endif PyObject* cursor_iternext(Cursor *self); @@ -157,24 +161,24 @@ int build_row_cast_map(Cursor* self) if (self->connection->detect_types | PARSE_COLNAMES) { colname = sqlite3_column_name(self->statement->st, i); + if (colname) { + for (pos = colname; *pos != 0; pos++) { + if (*pos == '[') { + type_start = pos + 1; + } else if (*pos == ']' && type_start != (const char*)-1) { + key = PyString_FromStringAndSize(type_start, pos - type_start); + if (!key) { + /* creating a string failed, but it is too complicated + * to propagate the error here, we just assume there is + * no converter and proceed */ + break; + } - for (pos = colname; *pos != 0; pos++) { - if (*pos == '[') { - type_start = pos + 1; - } else if (*pos == ']' && type_start != (const char*)-1) { - key = PyString_FromStringAndSize(type_start, pos - type_start); - if (!key) { - /* creating a string failed, but it is too complicated - * to propagate the error here, we just assume there is - * no converter and proceed */ + converter = PyDict_GetItem(converters, key); + Py_DECREF(key); break; } - - converter = PyDict_GetItem(converters, key); - Py_DECREF(key); - break; } - } } @@ -276,6 +280,7 @@ PyObject* _fetch_one_row(Cursor* self) void* raw_buffer; const char* val_str; char buf[200]; + const char* colname; Py_BEGIN_ALLOW_THREADS numcols = sqlite3_data_count(self->statement->st); @@ -340,8 +345,12 @@ PyObject* _fetch_one_row(Cursor* self) self->connection->text_factory == OptimizedUnicode ? 1 : 0); if (!converted) { + colname = sqlite3_column_name(self->statement->st, i); + if (colname) { + colname = "<unknown column name>"; + } PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column %s with text %s", - sqlite3_column_name(self->statement->st, i), val_str); + colname , val_str); PyErr_SetString(OperationalError, buf); } } else if (self->connection->text_factory == (PyObject*)&PyString_Type) { @@ -419,8 +428,7 @@ PyObject* _query_execute(Cursor* self, int multiple, PyObject* args) } else { /* sequence */ parameters_iter = PyObject_GetIter(second_argument); - if (!parameters_iter) - { + if (!parameters_iter) { return NULL; } } @@ -506,12 +514,7 @@ PyObject* _query_execute(Cursor* self, int multiple, PyObject* args) /* it's a DDL statement or something similar - we better COMMIT first so it works for all cases */ if (self->connection->inTransaction) { - func_args = PyTuple_New(0); - if (!func_args) { - goto error; - } - result = connection_commit(self->connection, func_args); - Py_DECREF(func_args); + result = connection_commit(self->connection, NULL); if (!result) { goto error; } @@ -701,7 +704,6 @@ PyObject* cursor_executescript(Cursor* self, PyObject* args) const char* script_cstr; sqlite3_stmt* statement; int rc; - PyObject* func_args; PyObject* result; int statement_completed = 0; @@ -728,12 +730,7 @@ PyObject* cursor_executescript(Cursor* self, PyObject* args) } /* commit first */ - func_args = PyTuple_New(0); - if (!func_args) { - goto error; - } - result = connection_commit(self->connection, func_args); - Py_DECREF(func_args); + result = connection_commit(self->connection, NULL); if (!result) { goto error; } @@ -977,6 +974,9 @@ static struct PyMemberDef cursor_members[] = {NULL} }; +static char cursor_doc[] = +PyDoc_STR("SQLite database cursor class."); + PyTypeObject CursorType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ @@ -999,7 +999,7 @@ PyTypeObject CursorType = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER|Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ + cursor_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h index 7f56799..831ff81 100644 --- a/Modules/_sqlite/cursor.h +++ b/Modules/_sqlite/cursor.h @@ -1,6 +1,6 @@ /* cursor.h - definitions for the cursor type * - * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de> + * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de> * * This file is part of pysqlite. * diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h index d2d9b65..f601bb3 100644 --- a/Modules/_sqlite/microprotocols.h +++ b/Modules/_sqlite/microprotocols.h @@ -54,6 +54,6 @@ extern PyObject *microprotocols_adapt( extern PyObject * psyco_microprotocols_adapt(Cursor* self, PyObject *args); #define psyco_microprotocols_adapt_doc \ - "adapt(obj, protocol, alternate) -> adapt obj to given protocol" - + "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard." + #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 1537e79..fb6eb06 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -167,12 +167,12 @@ void converters_init(PyObject* dict) static PyMethodDef module_methods[] = { {"connect", (PyCFunction)module_connect, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Creates a connection.")}, - {"complete_statement", (PyCFunction)module_complete, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Checks if a string contains a complete SQL statement.")}, + {"complete_statement", (PyCFunction)module_complete, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Checks if a string contains a complete SQL statement. Non-standard.")}, #ifdef HAVE_SHARED_CACHE - {"enable_shared_cache", (PyCFunction)module_enable_shared_cache, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Enable or disable shared cache mode for the calling thread.")}, + {"enable_shared_cache", (PyCFunction)module_enable_shared_cache, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Enable or disable shared cache mode for the calling thread. Experimental/Non-standard.")}, #endif - {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, PyDoc_STR("Registers an adapter with sqlite's adapter registry.")}, - {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, PyDoc_STR("Registers a converter with sqlite.")}, + {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, PyDoc_STR("Registers an adapter with pysqlite's adapter registry. Non-standard.")}, + {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, PyDoc_STR("Registers a converter with pysqlite. Non-standard.")}, {"adapt", (PyCFunction)psyco_microprotocols_adapt, METH_VARARGS, psyco_microprotocols_adapt_doc}, {NULL, NULL} }; diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h index 6694735..f3e2aa1 100644 --- a/Modules/_sqlite/module.h +++ b/Modules/_sqlite/module.h @@ -1,6 +1,6 @@ /* module.h - definitions for the module * - * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de> + * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de> * * This file is part of pysqlite. * @@ -25,7 +25,7 @@ #define PYSQLITE_MODULE_H #include "Python.h" -#define PYSQLITE_VERSION "2.2.0" +#define PYSQLITE_VERSION "2.2.2" extern PyObject* Error; extern PyObject* Warning; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 0c93651..55923e7 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -64,6 +64,7 @@ int statement_create(Statement* self, Connection* connection, PyObject* sql) return rc; } + self->in_weakreflist = NULL; self->sql = sql_str; sql_cstr = PyString_AsString(sql_str); @@ -304,6 +305,10 @@ void statement_dealloc(Statement* self) Py_XDECREF(self->sql); + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject*)self); + } + self->ob_type->tp_free((PyObject*)self); } @@ -398,12 +403,12 @@ PyTypeObject StatementType = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(Statement, in_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h index e45a0fc..57ee36f 100644 --- a/Modules/_sqlite/statement.h +++ b/Modules/_sqlite/statement.h @@ -38,6 +38,7 @@ typedef struct sqlite3_stmt* st; PyObject* sql; int in_use; + PyObject* in_weakreflist; /* List of weak references */ } Statement; extern PyTypeObject StatementType; diff --git a/Modules/_sre.c b/Modules/_sre.c index 4af08ed..06acb68 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -254,7 +254,7 @@ static void data_stack_dealloc(SRE_STATE* state) { if (state->data_stack) { - free(state->data_stack); + PyMem_FREE(state->data_stack); state->data_stack = NULL; } state->data_stack_size = state->data_stack_base = 0; @@ -270,7 +270,7 @@ data_stack_grow(SRE_STATE* state, int size) void* stack; cursize = minsize+minsize/4+1024; TRACE(("allocate/grow stack %d\n", cursize)); - stack = realloc(state->data_stack, cursize); + stack = PyMem_REALLOC(state->data_stack, cursize); if (!stack) { data_stack_dealloc(state); return SRE_ERROR_MEMORY; @@ -1163,7 +1163,7 @@ entrance: ctx->pattern[1], ctx->pattern[2])); /* install new repeat context */ - ctx->u.rep = (SRE_REPEAT*) malloc(sizeof(*ctx->u.rep)); + ctx->u.rep = (SRE_REPEAT*) PyObject_MALLOC(sizeof(*ctx->u.rep)); ctx->u.rep->count = -1; ctx->u.rep->pattern = ctx->pattern; ctx->u.rep->prev = state->repeat; @@ -1173,7 +1173,7 @@ entrance: state->ptr = ctx->ptr; DO_JUMP(JUMP_REPEAT, jump_repeat, ctx->pattern+ctx->pattern[0]); state->repeat = ctx->u.rep->prev; - free(ctx->u.rep); + PyObject_FREE(ctx->u.rep); if (ret) { RETURN_ON_ERROR(ret); diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 4c0da6f..f49391d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -183,10 +183,8 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file) int sockstate; self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ - if (self == NULL){ - errstr = "newPySSLObject error"; - goto fail; - } + if (self == NULL) + return NULL; memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); self->server_cert = NULL; diff --git a/Modules/structmodule.c b/Modules/_struct.c index 4713c0c..cb2e538 100644 --- a/Modules/structmodule.c +++ b/Modules/_struct.c @@ -3,35 +3,51 @@ /* New version supporting byte order, alignment and size options, character strings, and unsigned numbers */ +#define PY_SSIZE_T_CLEAN + #include "Python.h" +#include "structseq.h" +#include "structmember.h" #include <ctype.h> -PyDoc_STRVAR(struct__doc__, -"Functions to convert between Python values and C structs.\n\ -Python strings are used to hold the data representing the C struct\n\ -and also as format strings to describe the layout of data in the C struct.\n\ -\n\ -The optional first format char indicates byte order, size and alignment:\n\ - @: native order, size & alignment (default)\n\ - =: native order, std. size & alignment\n\ - <: little-endian, std. size & alignment\n\ - >: big-endian, std. size & alignment\n\ - !: same as >\n\ -\n\ -The remaining chars indicate types of args and must match exactly;\n\ -these can be preceded by a decimal repeat count:\n\ - x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ - h:short; H:unsigned short; i:int; I:unsigned int;\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 (with count byte).\n\ -Special case (only available in native format):\n\ - P:an integer type that is wide enough to hold a pointer.\n\ -Special case (not in native mode unless 'long long' in platform C):\n\ - q:long long; Q:unsigned long long\n\ -Whitespace between formats is ignored.\n\ -\n\ -The variable struct.error is an exception raised on errors."); +static PyTypeObject PyStructType; + +/* compatibility macros */ +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +/* The translation function for each format character is table driven */ +typedef struct _formatdef { + char format; + Py_ssize_t size; + Py_ssize_t alignment; + PyObject* (*unpack)(const char *, + const struct _formatdef *); + int (*pack)(char *, PyObject *, + const struct _formatdef *); +} formatdef; + +typedef struct _formatcode { + const struct _formatdef *fmtdef; + Py_ssize_t offset; + Py_ssize_t size; +} formatcode; + +/* Struct object interface */ + +typedef struct { + PyObject_HEAD + Py_ssize_t s_size; + Py_ssize_t s_len; + formatcode *s_codes; + PyObject *s_format; + PyObject *weakreflist; /* List of weak references */ +} PyStructObject; + + +#define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType) +#define PyStruct_CheckExact(op) ((op)->ob_type == &PyStructType) /* Exception */ @@ -127,9 +143,14 @@ get_ulong(PyObject *v, unsigned long *p) *p = x; return 0; } - else { - return get_long(v, (long *)p); + if (get_long(v, (long *)p) < 0) + return -1; + if (((long)*p) < 0) { + PyErr_SetString(StructError, + "unsigned argument is < 0"); + return -1; } + return 0; } #ifdef HAVE_LONG_LONG @@ -200,22 +221,40 @@ unpack_double(const char *p, /* start of 8-byte string */ return PyFloat_FromDouble(x); } +/* Helper to format the range error exceptions */ +static int +_range_error(char format, Py_ssize_t size, int is_unsigned) +{ + if (is_unsigned == 0) { + long smallest = 0, largest = 0; + Py_ssize_t i = size * 8; + while (--i > 0) { + smallest = (smallest * 2) - 1; + largest = (largest * 2) + 1; + } + PyErr_Format(StructError, + "'%c' format requires %ld <= number <= %ld", + format, + smallest, + largest); + } else { + unsigned long largest = 0; + Py_ssize_t i = size * 8; + while (--i >= 0) + largest = (largest * 2) + 1; + PyErr_Format(StructError, + "'%c' format requires 0 <= number <= %lu", + format, + largest); + } + return -1; +} -/* The translation function for each format character is table driven */ -typedef struct _formatdef { - char format; - int size; - int alignment; - PyObject* (*unpack)(const char *, - const struct _formatdef *); - int (*pack)(char *, PyObject *, - const struct _formatdef *); -} formatdef; /* A large number of small routines follow, with names of the form - [bln][up]_TYPE + [bln][up]_TYPE [bln] distiguishes among big-endian, little-endian and native. [pu] distiguishes between pack (to struct) and unpack (from struct). @@ -279,7 +318,13 @@ nu_uint(const char *p, const formatdef *f) { unsigned int x; memcpy((char *)&x, p, sizeof x); +#if (SIZEOF_LONG > SIZEOF_INT) + return PyInt_FromLong((long)x); +#else + if (x <= ((unsigned int)LONG_MAX)) + return PyInt_FromLong((long)x); return PyLong_FromUnsignedLong((unsigned long)x); +#endif } static PyObject * @@ -295,6 +340,8 @@ nu_ulong(const char *p, const formatdef *f) { unsigned long x; memcpy((char *)&x, p, sizeof x); + if (x <= LONG_MAX) + return PyInt_FromLong((long)x); return PyLong_FromUnsignedLong(x); } @@ -308,6 +355,8 @@ nu_longlong(const char *p, const formatdef *f) { PY_LONG_LONG x; memcpy((char *)&x, p, sizeof x); + if (x >= LONG_MIN && x <= LONG_MAX) + return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); return PyLong_FromLongLong(x); } @@ -316,6 +365,8 @@ nu_ulonglong(const char *p, const formatdef *f) { unsigned PY_LONG_LONG x; memcpy((char *)&x, p, sizeof x); + if (x <= LONG_MAX) + return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); return PyLong_FromUnsignedLongLong(x); } @@ -353,7 +404,7 @@ np_byte(char *p, PyObject *v, const formatdef *f) return -1; if (x < -128 || x > 127){ PyErr_SetString(StructError, - "byte format requires -128<=number<=127"); + "byte format requires -128 <= number <= 127"); return -1; } *p = (char)x; @@ -368,7 +419,7 @@ np_ubyte(char *p, PyObject *v, const formatdef *f) return -1; if (x < 0 || x > 255){ PyErr_SetString(StructError, - "ubyte format requires 0<=number<=255"); + "ubyte format requires 0 <= number <= 255"); return -1; } *p = (char)x; @@ -397,7 +448,7 @@ np_short(char *p, PyObject *v, const formatdef *f) if (x < SHRT_MIN || x > SHRT_MAX){ PyErr_SetString(StructError, "short format requires " STRINGIFY(SHRT_MIN) - "<=number<=" STRINGIFY(SHRT_MAX)); + " <= number <= " STRINGIFY(SHRT_MAX)); return -1; } y = (short)x; @@ -414,7 +465,7 @@ np_ushort(char *p, PyObject *v, const formatdef *f) return -1; if (x < 0 || x > USHRT_MAX){ PyErr_SetString(StructError, - "short format requires 0<=number<=" STRINGIFY(USHRT_MAX)); + "short format requires 0 <= number <= " STRINGIFY(USHRT_MAX)); return -1; } y = (unsigned short)x; @@ -429,6 +480,10 @@ np_int(char *p, PyObject *v, const formatdef *f) int y; if (get_long(v, &x) < 0) return -1; +#if (SIZEOF_LONG > SIZEOF_INT) + if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) + return _range_error(f->format, sizeof(y), 0); +#endif y = (int)x; memcpy(p, (char *)&y, sizeof y); return 0; @@ -440,8 +495,12 @@ np_uint(char *p, PyObject *v, const formatdef *f) unsigned long x; unsigned int y; if (get_ulong(v, &x) < 0) - return -1; + return _range_error(f->format, sizeof(y), 1); y = (unsigned int)x; +#if (SIZEOF_LONG > SIZEOF_INT) + if (x > ((unsigned long)UINT_MAX)) + return _range_error(f->format, sizeof(y), 1); +#endif memcpy(p, (char *)&y, sizeof y); return 0; } @@ -461,7 +520,7 @@ np_ulong(char *p, PyObject *v, const formatdef *f) { unsigned long x; if (get_ulong(v, &x) < 0) - return -1; + return _range_error(f->format, sizeof(x), 1); memcpy(p, (char *)&x, sizeof x); return 0; } @@ -545,13 +604,13 @@ static formatdef native_table[] = { {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint}, {'l', sizeof(long), LONG_ALIGN, nu_long, np_long}, {'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}, #ifdef HAVE_LONG_LONG {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, #endif + {'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} }; @@ -561,13 +620,13 @@ static PyObject * bu_int(const char *p, const formatdef *f) { long x = 0; - int i = f->size; + Py_ssize_t i = f->size; do { x = (x<<8) | (*p++ & 0xFF); } while (--i > 0); /* Extend the sign bit. */ if (SIZEOF_LONG > f->size) - x |= -(x & (1L << (8*f->size - 1))); + x |= -(x & (1L << ((8 * f->size) - 1))); return PyInt_FromLong(x); } @@ -575,32 +634,56 @@ static PyObject * bu_uint(const char *p, const formatdef *f) { unsigned long x = 0; - int i = f->size; + Py_ssize_t i = f->size; do { x = (x<<8) | (*p++ & 0xFF); } while (--i > 0); - if (f->size >= 4) - return PyLong_FromUnsignedLong(x); - else + if (x <= LONG_MAX) return PyInt_FromLong((long)x); + return PyLong_FromUnsignedLong(x); } static PyObject * bu_longlong(const char *p, const formatdef *f) { +#ifdef HAVE_LONG_LONG + PY_LONG_LONG x = 0; + Py_ssize_t i = f->size; + do { + x = (x<<8) | (*p++ & 0xFF); + } while (--i > 0); + /* Extend the sign bit. */ + if (SIZEOF_LONG_LONG > f->size) + x |= -(x & (1L << ((8 * f->size) - 1))); + if (x >= LONG_MIN && x <= LONG_MAX) + return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); + return PyLong_FromLongLong(x); +#else return _PyLong_FromByteArray((const unsigned char *)p, 8, 0, /* little-endian */ 1 /* signed */); +#endif } static PyObject * bu_ulonglong(const char *p, const formatdef *f) { +#ifdef HAVE_LONG_LONG + unsigned PY_LONG_LONG x = 0; + Py_ssize_t i = f->size; + do { + x = (x<<8) | (*p++ & 0xFF); + } while (--i > 0); + if (x <= LONG_MAX) + return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); + return PyLong_FromUnsignedLongLong(x); +#else return _PyLong_FromByteArray((const unsigned char *)p, 8, 0, /* little-endian */ 0 /* signed */); +#endif } static PyObject * @@ -619,10 +702,18 @@ static int bp_int(char *p, PyObject *v, const formatdef *f) { long x; - int i; + Py_ssize_t i; if (get_long(v, &x) < 0) return -1; i = f->size; + if (i != SIZEOF_LONG) { + if ((i == 2) && (x < -32768 || x > 32767)) + return _range_error(f->format, i, 0); +#if (SIZEOF_LONG != 4) + else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) + return _range_error(f->format, i, 0); +#endif + } do { p[--i] = (char)x; x >>= 8; @@ -634,10 +725,16 @@ static int bp_uint(char *p, PyObject *v, const formatdef *f) { unsigned long x; - int i; + Py_ssize_t i; if (get_ulong(v, &x) < 0) return -1; i = f->size; + if (i != SIZEOF_LONG) { + unsigned long maxint = 1; + maxint <<= (unsigned long)(i * 8); + if (x >= maxint) + return _range_error(f->format, f->size, 1); + } do { p[--i] = (char)x; x >>= 8; @@ -703,8 +800,8 @@ bp_double(char *p, PyObject *v, const formatdef *f) static formatdef bigendian_table[] = { {'x', 1, 0, NULL}, - {'b', 1, 0, bu_int, bp_int}, - {'B', 1, 0, bu_uint, bp_int}, + {'b', 1, 0, nu_byte, np_byte}, + {'B', 1, 0, nu_ubyte, np_ubyte}, {'c', 1, 0, nu_char, np_char}, {'s', 1, 0, NULL}, {'p', 1, 0, NULL}, @@ -727,13 +824,13 @@ static PyObject * lu_int(const char *p, const formatdef *f) { long x = 0; - int i = f->size; + Py_ssize_t i = f->size; do { x = (x<<8) | (p[--i] & 0xFF); } while (i > 0); /* Extend the sign bit. */ if (SIZEOF_LONG > f->size) - x |= -(x & (1L << (8*f->size - 1))); + x |= -(x & (1L << ((8 * f->size) - 1))); return PyInt_FromLong(x); } @@ -741,32 +838,56 @@ static PyObject * lu_uint(const char *p, const formatdef *f) { unsigned long x = 0; - int i = f->size; + Py_ssize_t i = f->size; do { x = (x<<8) | (p[--i] & 0xFF); } while (i > 0); - if (f->size >= 4) - return PyLong_FromUnsignedLong(x); - else + if (x <= LONG_MAX) return PyInt_FromLong((long)x); + return PyLong_FromUnsignedLong((long)x); } static PyObject * lu_longlong(const char *p, const formatdef *f) { +#ifdef HAVE_LONG_LONG + PY_LONG_LONG x = 0; + Py_ssize_t i = f->size; + do { + x = (x<<8) | (p[--i] & 0xFF); + } while (i > 0); + /* Extend the sign bit. */ + if (SIZEOF_LONG_LONG > f->size) + x |= -(x & (1L << ((8 * f->size) - 1))); + if (x >= LONG_MIN && x <= LONG_MAX) + return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); + return PyLong_FromLongLong(x); +#else return _PyLong_FromByteArray((const unsigned char *)p, 8, 1, /* little-endian */ 1 /* signed */); +#endif } static PyObject * lu_ulonglong(const char *p, const formatdef *f) { +#ifdef HAVE_LONG_LONG + unsigned PY_LONG_LONG x = 0; + Py_ssize_t i = f->size; + do { + x = (x<<8) | (p[--i] & 0xFF); + } while (i > 0); + if (x <= LONG_MAX) + return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); + return PyLong_FromUnsignedLongLong(x); +#else return _PyLong_FromByteArray((const unsigned char *)p, 8, 1, /* little-endian */ 0 /* signed */); +#endif } static PyObject * @@ -785,10 +906,18 @@ static int lp_int(char *p, PyObject *v, const formatdef *f) { long x; - int i; + Py_ssize_t i; if (get_long(v, &x) < 0) return -1; i = f->size; + if (i != SIZEOF_LONG) { + if ((i == 2) && (x < -32768 || x > 32767)) + return _range_error(f->format, i, 0); +#if (SIZEOF_LONG != 4) + else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) + return _range_error(f->format, i, 0); +#endif + } do { *p++ = (char)x; x >>= 8; @@ -800,10 +929,16 @@ static int lp_uint(char *p, PyObject *v, const formatdef *f) { unsigned long x; - int i; + Py_ssize_t i; if (get_ulong(v, &x) < 0) return -1; i = f->size; + if (i != SIZEOF_LONG) { + unsigned long maxint = 1; + maxint <<= (unsigned long)(i * 8); + if (x >= maxint) + return _range_error(f->format, f->size, 1); + } do { *p++ = (char)x; x >>= 8; @@ -869,8 +1004,8 @@ lp_double(char *p, PyObject *v, const formatdef *f) static formatdef lilendian_table[] = { {'x', 1, 0, NULL}, - {'b', 1, 0, lu_int, lp_int}, - {'B', 1, 0, lu_uint, lp_int}, + {'b', 1, 0, nu_byte, np_byte}, + {'B', 1, 0, nu_ubyte, np_ubyte}, {'c', 1, 0, nu_char, np_char}, {'s', 1, 0, NULL}, {'p', 1, 0, NULL}, @@ -933,7 +1068,7 @@ getentry(int c, const formatdef *f) /* Align a size according to a format code */ static int -align(int size, int c, const formatdef *e) +align(Py_ssize_t size, char c, const formatdef *e) { if (e->format == c) { if (e->alignment) { @@ -949,15 +1084,24 @@ align(int size, int c, const formatdef *e) /* calculate the size of a format string */ static int -calcsize(const char *fmt, const formatdef *f) +prepare_s(PyStructObject *self) { + const formatdef *f; const formatdef *e; + formatcode *codes; + const char *s; + const char *fmt; char c; - int size, num, itemsize, x; + Py_ssize_t size, len, num, itemsize, x; + + fmt = PyString_AS_STRING(self->s_format); + f = whichtable((char **)&fmt); + s = fmt; size = 0; + len = 0; while ((c = *s++) != '\0') { if (isspace(Py_CHARMASK(c))) continue; @@ -982,6 +1126,14 @@ calcsize(const char *fmt, const formatdef *f) e = getentry(c, f); if (e == NULL) return -1; + + switch (c) { + case 's': /* fall through */ + case 'p': len++; break; + case 'x': break; + default: len += num; break; + } + itemsize = e->size; size = align(size, c, e); x = num * itemsize; @@ -993,78 +1145,24 @@ calcsize(const char *fmt, const formatdef *f) } } - return size; -} - - -PyDoc_STRVAR(calcsize__doc__, -"calcsize(fmt) -> int\n\ -Return size of C struct described by format string fmt.\n\ -See struct.__doc__ for more on format strings."); - -static PyObject * -struct_calcsize(PyObject *self, PyObject *args) -{ - char *fmt; - const formatdef *f; - int size; - - if (!PyArg_ParseTuple(args, "s:calcsize", &fmt)) - return NULL; - f = whichtable(&fmt); - size = calcsize(fmt, f); - if (size < 0) - return NULL; - return PyInt_FromLong((long)size); -} - - -PyDoc_STRVAR(pack__doc__, -"pack(fmt, v1, v2, ...) -> string\n\ -Return string containing values v1, v2, ... packed according to fmt.\n\ -See struct.__doc__ for more on format strings."); - -static PyObject * -struct_pack(PyObject *self, PyObject *args) -{ - const formatdef *f, *e; - PyObject *format, *result, *v; - char *fmt; - int size, num; - Py_ssize_t i, n; - char *s, *res, *restart, *nres; - char c; - - if (args == NULL || !PyTuple_Check(args) || - (n = PyTuple_Size(args)) < 1) - { - PyErr_SetString(PyExc_TypeError, - "struct.pack requires at least one argument"); - return NULL; + self->s_size = size; + self->s_len = len; + codes = PyMem_MALLOC((len + 1) * sizeof(formatcode)); + if (codes == NULL) { + PyErr_NoMemory(); + return -1; } - format = PyTuple_GetItem(args, 0); - fmt = PyString_AsString(format); - if (!fmt) - return NULL; - f = whichtable(&fmt); - size = calcsize(fmt, f); - if (size < 0) - return NULL; - result = PyString_FromStringAndSize((char *)NULL, size); - if (result == NULL) - return NULL; - + self->s_codes = codes; + s = fmt; - i = 1; - res = restart = PyString_AsString(result); - + size = 0; while ((c = *s++) != '\0') { if (isspace(Py_CHARMASK(c))) continue; if ('0' <= c && c <= '9') { num = c - '0'; while ('0' <= (c = *s++) && c <= '9') - num = num*10 + (c - '0'); + num = num*10 + (c - '0'); if (c == '\0') break; } @@ -1072,222 +1170,491 @@ struct_pack(PyObject *self, PyObject *args) num = 1; e = getentry(c, f); - if (e == NULL) - goto fail; - nres = restart + align((int)(res-restart), c, e); - /* Fill padd bytes with zeros */ - while (res < nres) - *res++ = '\0'; - if (num == 0 && c != 's') - continue; - do { - if (c == 'x') { - /* doesn't consume arguments */ - memset(res, '\0', num); - res += num; - break; + + size = align(size, c, e); + if (c == 's' || c == 'p') { + codes->offset = size; + codes->size = num; + codes->fmtdef = e; + codes++; + size += num; + } else if (c == 'x') { + size += num; + } else { + while (--num >= 0) { + codes->offset = size; + codes->size = e->size; + codes->fmtdef = e; + codes++; + size += e->size; } - if (i >= n) { - PyErr_SetString(StructError, - "insufficient arguments to pack"); + } + } + codes->fmtdef = NULL; + codes->offset = size; + codes->size = 0; + + return 0; +} + +static PyObject * +s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *self; + + assert(type != NULL && type->tp_alloc != NULL); + + self = type->tp_alloc(type, 0); + if (self != NULL) { + PyStructObject *s = (PyStructObject*)self; + Py_INCREF(Py_None); + s->s_format = Py_None; + s->s_codes = NULL; + s->s_size = -1; + s->s_len = -1; + } + return self; +} + +static int +s_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyStructObject *soself = (PyStructObject *)self; + PyObject *o_format = NULL; + int ret = 0; + static char *kwlist[] = {"format", 0}; + + assert(PyStruct_Check(self)); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:Struct", kwlist, + &o_format)) + return -1; + + Py_INCREF(o_format); + Py_XDECREF(soself->s_format); + soself->s_format = o_format; + + ret = prepare_s(soself); + return ret; +} + +static void +s_dealloc(PyStructObject *s) +{ + if (s->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)s); + if (s->s_codes != NULL) { + PyMem_FREE(s->s_codes); + } + Py_XDECREF(s->s_format); + s->ob_type->tp_free((PyObject *)s); +} + +static PyObject * +s_unpack_internal(PyStructObject *soself, char *startfrom) { + formatcode *code; + Py_ssize_t i = 0; + PyObject *result = PyTuple_New(soself->s_len); + if (result == NULL) + return NULL; + + for (code = soself->s_codes; code->fmtdef != NULL; code++) { + PyObject *v; + const formatdef *e = code->fmtdef; + const char *res = startfrom + code->offset; + if (e->format == 's') { + v = PyString_FromStringAndSize(res, code->size); + if (v == NULL) goto fail; - } - v = PyTuple_GetItem(args, i++); + PyTuple_SET_ITEM(result, i++, v); + } else if (e->format == 'p') { + Py_ssize_t n = *(unsigned char*)res; + if (n >= code->size) + n = code->size - 1; + v = PyString_FromStringAndSize(res + 1, n); if (v == NULL) goto fail; - if (c == 's') { - /* num is string size, not repeat count */ - Py_ssize_t n; - if (!PyString_Check(v)) { - PyErr_SetString(StructError, - "argument for 's' must be a string"); - goto fail; - } - n = PyString_Size(v); - if (n > num) - n = num; - if (n > 0) - memcpy(res, PyString_AsString(v), n); - if (n < num) - memset(res+n, '\0', num-n); - res += num; - break; - } - else if (c == 'p') { - /* num is string size + 1, - to fit in the count byte */ - Py_ssize_t n; - num--; /* now num is max string size */ - if (!PyString_Check(v)) { - PyErr_SetString(StructError, - "argument for 'p' must be a string"); - goto fail; - } - n = PyString_Size(v); - if (n > num) - n = num; - if (n > 0) - memcpy(res+1, PyString_AsString(v), n); - if (n < num) - /* no real need, just to be nice */ - memset(res+1+n, '\0', num-n); - if (n > 255) - n = 255; - /* store the length byte */ - *res++ = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); - res += num; - break; - } - else { - if (e->pack(res, v, e) < 0) - goto fail; - res += e->size; - } - } while (--num > 0); - } - - if (i < n) { - PyErr_SetString(StructError, - "too many arguments for pack format"); - goto fail; + PyTuple_SET_ITEM(result, i++, v); + } else { + v = e->unpack(res, e); + if (v == NULL) + goto fail; + PyTuple_SET_ITEM(result, i++, v); + } } return result; - - fail: +fail: Py_DECREF(result); return NULL; } -PyDoc_STRVAR(unpack__doc__, -"unpack(fmt, string) -> (v1, v2, ...)\n\ -Unpack the string, containing packed C structure data, according\n\ -to fmt. Requires len(string)==calcsize(fmt).\n\ +PyDoc_STRVAR(s_unpack__doc__, +"S.unpack(str) -> (v1, v2, ...)\n\ +\n\ +Return tuple containing values unpacked according to this Struct's format.\n\ +Requires len(str) == self.size. See struct.__doc__ for more on format\n\ +strings."); + +static PyObject * +s_unpack(PyObject *self, PyObject *inputstr) +{ + PyStructObject *soself = (PyStructObject *)self; + assert(PyStruct_Check(self)); + assert(soself->s_codes != NULL); + if (inputstr == NULL || !PyString_Check(inputstr) || + PyString_GET_SIZE(inputstr) != soself->s_size) { + PyErr_Format(StructError, + "unpack requires a string argument of length %zd", soself->s_size); + return NULL; + } + return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); +} + +PyDoc_STRVAR(s_unpack_from__doc__, +"S.unpack_from(buffer[, offset]) -> (v1, v2, ...)\n\ +\n\ +Return tuple containing values unpacked according to this Struct's format.\n\ +Unlike unpack, unpack_from can unpack values from any object supporting\n\ +the buffer API, not just str. Requires len(buffer[offset:]) >= self.size.\n\ See struct.__doc__ for more on format strings."); static PyObject * -struct_unpack(PyObject *self, PyObject *args) +s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds) { - const formatdef *f, *e; - char *str, *start, *fmt, *s; - char c; - int len, size, num; - PyObject *res, *v; - - if (!PyArg_ParseTuple(args, "ss#:unpack", &fmt, &start, &len)) - return NULL; - f = whichtable(&fmt); - size = calcsize(fmt, f); - if (size < 0) + static char *kwlist[] = {"buffer", "offset", 0}; +#if (PY_VERSION_HEX < 0x02050000) + static char *fmt = "z#|i:unpack_from"; +#else + static char *fmt = "z#|n:unpack_from"; +#endif + Py_ssize_t buffer_len = 0, offset = 0; + char *buffer = NULL; + PyStructObject *soself = (PyStructObject *)self; + assert(PyStruct_Check(self)); + assert(soself->s_codes != NULL); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist, + &buffer, &buffer_len, &offset)) return NULL; - if (size != len) { - PyErr_SetString(StructError, - "unpack str size does not match format"); + + if (buffer == NULL) { + PyErr_Format(StructError, + "unpack_from requires a buffer argument"); return NULL; } - res = PyList_New(0); - if (res == NULL) + + if (offset < 0) + offset += buffer_len; + + if (offset < 0 || (buffer_len - offset) < soself->s_size) { + PyErr_Format(StructError, + "unpack_from requires a buffer of at least %zd bytes", + soself->s_size); return NULL; - str = start; - s = fmt; - while ((c = *s++) != '\0') { - if (isspace(Py_CHARMASK(c))) - continue; - if ('0' <= c && c <= '9') { - num = c - '0'; - while ('0' <= (c = *s++) && c <= '9') - num = num*10 + (c - '0'); - if (c == '\0') - break; - } - else - num = 1; + } + return s_unpack_internal(soself, buffer + offset); +} - e = getentry(c, f); - if (e == NULL) - goto fail; - str = start + align((int)(str-start), c, e); - if (num == 0 && c != 's') - continue; - do { - if (c == 'x') { - str += num; - break; - } - if (c == 's') { - /* num is string size, not repeat count */ - v = PyString_FromStringAndSize(str, num); - if (v == NULL) - goto fail; - str += num; - num = 0; - } - else if (c == 'p') { - /* num is string buffer size, - not repeat count */ - int n = *(unsigned char*)str; - /* first byte (unsigned) is string size */ - if (n >= num) - n = num-1; - v = PyString_FromStringAndSize(str+1, n); - if (v == NULL) - goto fail; - str += num; - num = 0; +/* + * Guts of the pack function. + * + * Takes a struct object, a tuple of arguments, and offset in that tuple of + * argument for where to start processing the arguments for packing, and a + * character buffer for writing the packed string. The caller must insure + * that the buffer may contain the required length for packing the arguments. + * 0 is returned on success, 1 is returned if there is an error. + * + */ +static int +s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf) +{ + formatcode *code; + Py_ssize_t i; + + memset(buf, '\0', soself->s_size); + i = offset; + for (code = soself->s_codes; code->fmtdef != NULL; code++) { + Py_ssize_t n; + PyObject *v; + const formatdef *e = code->fmtdef; + char *res = buf + code->offset; + if (e->format == 's') { + v = PyTuple_GET_ITEM(args, i++); + if (!PyString_Check(v)) { + PyErr_SetString(StructError, + "argument for 's' must be a string"); + return -1; } - else { - v = e->unpack(str, e); - if (v == NULL) - goto fail; - str += e->size; + n = PyString_GET_SIZE(v); + if (n > code->size) + n = code->size; + if (n > 0) + memcpy(res, PyString_AS_STRING(v), n); + } else if (e->format == 'p') { + v = PyTuple_GET_ITEM(args, i++); + if (!PyString_Check(v)) { + PyErr_SetString(StructError, + "argument for 'p' must be a string"); + return -1; } - if (v == NULL || PyList_Append(res, v) < 0) - goto fail; - Py_DECREF(v); - } while (--num > 0); + n = PyString_GET_SIZE(v); + if (n > (code->size - 1)) + n = code->size - 1; + if (n > 0) + memcpy(res + 1, PyString_AS_STRING(v), n); + if (n > 255) + n = 255; + *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); + } else { + v = PyTuple_GET_ITEM(args, i++); + if (e->pack(res, v, e) < 0) + return -1; + } } + + /* Success */ + return 0; +} - v = PyList_AsTuple(res); - Py_DECREF(res); - return v; - fail: - Py_DECREF(res); - return NULL; +PyDoc_STRVAR(s_pack__doc__, +"S.pack(v1, v2, ...) -> string\n\ +\n\ +Return a string containing values v1, v2, ... packed according to this\n\ +Struct's format. See struct.__doc__ for more on format strings."); + +static PyObject * +s_pack(PyObject *self, PyObject *args) +{ + PyStructObject *soself; + PyObject *result; + + /* Validate arguments. */ + soself = (PyStructObject *)self; + assert(PyStruct_Check(self)); + assert(soself->s_codes != NULL); + if (args == NULL || !PyTuple_Check(args) || + PyTuple_GET_SIZE(args) != soself->s_len) + { + PyErr_Format(StructError, + "pack requires exactly %zd arguments", soself->s_len); + return NULL; + } + + /* Allocate a new string */ + result = PyString_FromStringAndSize((char *)NULL, soself->s_size); + if (result == NULL) + return NULL; + + /* Call the guts */ + if ( s_pack_internal(soself, args, 0, PyString_AS_STRING(result)) != 0 ) { + Py_DECREF(result); + return NULL; + } + + return result; } +PyDoc_STRVAR(s_pack_to__doc__, +"S.pack_to(buffer, offset, v1, v2, ...)\n\ +\n\ +Pack the values v2, v2, ... according to this Struct's format, write \n\ +the packed bytes into the writable buffer buf starting at offset. Note\n\ +that the offset is not an optional argument. See struct.__doc__ for \n\ +more on format strings."); + +static PyObject * +s_pack_to(PyObject *self, PyObject *args) +{ + PyStructObject *soself; + char *buffer; + Py_ssize_t buffer_len, offset; + + /* Validate arguments. +1 is for the first arg as buffer. */ + soself = (PyStructObject *)self; + assert(PyStruct_Check(self)); + assert(soself->s_codes != NULL); + if (args == NULL || !PyTuple_Check(args) || + PyTuple_GET_SIZE(args) != (soself->s_len + 2)) + { + PyErr_Format(StructError, + "pack_to requires exactly %zd arguments", + (soself->s_len + 2)); + return NULL; + } + + /* Extract a writable memory buffer from the first argument */ + if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0), + (void**)&buffer, &buffer_len) == -1 ) { + return NULL; + } + assert( buffer_len >= 0 ); + + /* Extract the offset from the first argument */ + offset = PyInt_AsLong(PyTuple_GET_ITEM(args, 1)); + + /* Support negative offsets. */ + if (offset < 0) + offset += buffer_len; + + /* Check boundaries */ + if (offset < 0 || (buffer_len - offset) < soself->s_size) { + PyErr_Format(StructError, + "pack_to requires a buffer of at least %zd bytes", + soself->s_size); + return NULL; + } + + /* Call the guts */ + if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) { + return NULL; + } + + return Py_None; +} + +static PyObject * +s_get_format(PyStructObject *self, void *unused) +{ + Py_INCREF(self->s_format); + return self->s_format; +} + +static PyObject * +s_get_size(PyStructObject *self, void *unused) +{ + return PyInt_FromSsize_t(self->s_size); +} /* List of functions */ -static PyMethodDef struct_methods[] = { - {"calcsize", struct_calcsize, METH_VARARGS, calcsize__doc__}, - {"pack", struct_pack, METH_VARARGS, pack__doc__}, - {"unpack", struct_unpack, METH_VARARGS, unpack__doc__}, - {NULL, NULL} /* sentinel */ +static struct PyMethodDef s_methods[] = { + {"pack", (PyCFunction)s_pack, METH_VARARGS, s_pack__doc__}, + {"pack_to", (PyCFunction)s_pack_to, METH_VARARGS, s_pack_to__doc__}, + {"unpack", (PyCFunction)s_unpack, METH_O, s_unpack__doc__}, + {"unpack_from", (PyCFunction)s_unpack_from, METH_KEYWORDS, s_unpack_from__doc__}, + {NULL, NULL} /* sentinel */ }; +PyDoc_STRVAR(s__doc__, "Compiled struct object"); + +#define OFF(x) offsetof(PyStructObject, x) + +static PyGetSetDef s_getsetlist[] = { + {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL}, + {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL}, + {NULL} /* sentinel */ +}; + +static +PyTypeObject PyStructType = { + PyObject_HEAD_INIT(NULL) + 0, + "Struct", + sizeof(PyStructObject), + 0, + (destructor)s_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS,/* tp_flags */ + s__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(PyStructObject, weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + s_methods, /* tp_methods */ + NULL, /* tp_members */ + s_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + s_init, /* tp_init */ + PyType_GenericAlloc,/* tp_alloc */ + s_new, /* tp_new */ + PyObject_Del, /* tp_free */ +}; /* Module initialization */ PyMODINIT_FUNC -initstruct(void) +init_struct(void) { - PyObject *m; - - /* Create the module and add the functions */ - m = Py_InitModule4("struct", struct_methods, struct__doc__, - (PyObject*)NULL, PYTHON_API_VERSION); + PyObject *m = Py_InitModule("_struct", NULL); if (m == NULL) return; + PyStructType.ob_type = &PyType_Type; + if (PyType_Ready(&PyStructType) < 0) + return; + + /* Check endian and swap in faster functions */ + { + int one = 1; + formatdef *native = native_table; + formatdef *other, *ptr; + if ((int)*(unsigned char*)&one) + other = lilendian_table; + else + other = bigendian_table; + /* Scan through the native table, find a matching + entry in the endian table and swap in the + native implementations whenever possible + (64-bit platforms may not have "standard" sizes) */ + while (native->format != '\0' && other->format != '\0') { + ptr = other; + while (ptr->format != '\0') { + if (ptr->format == native->format) { + /* Match faster when formats are + listed in the same order */ + if (ptr == other) + other++; + /* Only use the trick if the + size matches */ + if (ptr->size != native->size) + break; + /* Skip float and double, could be + "unknown" float format */ + if (ptr->format == 'd' || ptr->format == 'f') + break; + ptr->pack = native->pack; + ptr->unpack = native->unpack; + break; + } + ptr++; + } + native++; + } + } + /* Add some symbolic constants to the module */ if (StructError == NULL) { StructError = PyErr_NewException("struct.error", NULL, NULL); if (StructError == NULL) return; } + Py_INCREF(StructError); PyModule_AddObject(m, "error", StructError); + + Py_INCREF((PyObject*)&PyStructType); + PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType); } diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index e8881dc..6b9dffd 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -486,8 +486,8 @@ test_u_code(PyObject *self) return Py_None; } -static -PyObject *codec_incrementalencoder(PyObject *self, PyObject *args) +static PyObject * +codec_incrementalencoder(PyObject *self, PyObject *args) { const char *encoding, *errors = NULL; if (!PyArg_ParseTuple(args, "s|s:test_incrementalencoder", @@ -496,8 +496,8 @@ PyObject *codec_incrementalencoder(PyObject *self, PyObject *args) return PyCodec_IncrementalEncoder(encoding, errors); } -static -PyObject *codec_incrementaldecoder(PyObject *self, PyObject *args) +static PyObject * +codec_incrementaldecoder(PyObject *self, PyObject *args) { const char *encoding, *errors = NULL; if (!PyArg_ParseTuple(args, "s|s:test_incrementaldecoder", @@ -660,6 +660,42 @@ test_thread_state(PyObject *self, PyObject *args) } #endif +/* Some tests of PyString_FromFormat(). This needs more tests. */ +static PyObject * +test_string_from_format(PyObject *self, PyObject *args) +{ + PyObject *result; + char *msg; + +#define CHECK_1_FORMAT(FORMAT, TYPE) \ + result = PyString_FromFormat(FORMAT, (TYPE)1); \ + if (result == NULL) \ + return NULL; \ + if (strcmp(PyString_AsString(result), "1")) { \ + msg = FORMAT " failed at 1"; \ + goto Fail; \ + } \ + Py_DECREF(result) + + CHECK_1_FORMAT("%d", int); + CHECK_1_FORMAT("%ld", long); + /* The z width modifier was added in Python 2.5. */ + CHECK_1_FORMAT("%zd", Py_ssize_t); + + /* The u type code was added in Python 2.5. */ + CHECK_1_FORMAT("%u", unsigned int); + CHECK_1_FORMAT("%lu", unsigned long); + CHECK_1_FORMAT("%zu", size_t); + + Py_RETURN_NONE; + + Fail: + Py_XDECREF(result); + return raiseTestError("test_string_from_format", msg); + +#undef CHECK_1_FORMAT +} + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"test_config", (PyCFunction)test_config, METH_NOARGS}, @@ -669,6 +705,7 @@ static PyMethodDef TestMethods[] = { {"test_long_numbits", (PyCFunction)test_long_numbits, METH_NOARGS}, {"test_k_code", (PyCFunction)test_k_code, METH_NOARGS}, {"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS}, + {"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS}, {"getargs_b", getargs_b, METH_VARARGS}, {"getargs_B", getargs_B, METH_VARARGS}, diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index c17b6c6..77583b7 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -2619,21 +2619,32 @@ Tkapp_InterpAddr(PyObject *self, PyObject *args) static PyObject * Tkapp_TkInit(PyObject *self, PyObject *args) { + static int has_failed; Tcl_Interp *interp = Tkapp_Interp(self); Tk_Window main_window; const char * _tk_exists = NULL; - PyObject *res = NULL; int err; main_window = Tk_MainWindow(interp); + /* In all current versions of Tk (including 8.4.13), Tk_Init + deadlocks on the second call when the first call failed. + To avoid the deadlock, we just refuse the second call through + a static variable. */ + if (has_failed) { + PyErr_SetString(Tkinter_TclError, + "Calling Tk_Init again after a previous call failed might deadlock"); + return NULL; + } + /* We want to guard against calling Tk_Init() multiple times */ CHECK_TCL_APPARTMENT; ENTER_TCL err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version"); ENTER_OVERLAP if (err == TCL_ERROR) { - /* XXX: shouldn't we do something with res? */ - res = Tkinter_Error(self); + /* This sets an exception, but we cannot return right + away because we need to exit the overlap first. */ + Tkinter_Error(self); } else { _tk_exists = Tkapp_Result(self); } @@ -2644,6 +2655,7 @@ Tkapp_TkInit(PyObject *self, PyObject *args) if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) { if (Tk_Init(interp) == TCL_ERROR) { PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self))); + has_failed = 1; return NULL; } } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 52a7f5e..af12769 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1975,9 +1975,9 @@ static PyTypeObject Arraytype = { 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)array_repr, /* tp_repr */ - 0, /* tp_as _number*/ - &array_as_sequence, /* tp_as _sequence*/ - &array_as_mapping, /* tp_as _mapping*/ + 0, /* tp_as_number*/ + &array_as_sequence, /* tp_as_sequence*/ + &array_as_mapping, /* tp_as_mapping*/ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ diff --git a/Modules/cPickle.c b/Modules/cPickle.c index 18df599..85fd459 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -1151,7 +1151,9 @@ save_float(Picklerobject *self, PyObject *args) else { char c_str[250]; c_str[0] = FLOAT; - PyOS_snprintf(c_str + 1, sizeof(c_str) - 1, "%.17g\n", x); + PyOS_ascii_formatd(c_str + 1, sizeof(c_str) - 2, "%.17g", x); + /* Extend the formatted string with a newline character */ + strcat(c_str, "\n"); if (self->write_func(self, c_str, strlen(c_str)) < 0) return -1; @@ -3071,8 +3073,8 @@ find_class(PyObject *py_module_name, PyObject *py_global_name, PyObject *fc) "pickles are not supported."); return NULL; } - return PyObject_CallFunction(fc, "OO", py_module_name, - py_global_name); + return PyObject_CallFunctionObjArgs(fc, py_module_name, + py_global_name, NULL); } module = PySys_GetObject("modules"); @@ -5623,7 +5625,6 @@ init_stuff(PyObject *module_dict) if (!( t=PyDict_New())) return -1; if (!( r=PyRun_String( - "def __init__(self, *args): self.args=args\n\n" "def __str__(self):\n" " return self.args and ('%s' % self.args[0]) or '(what)'\n", Py_file_input, @@ -5643,7 +5644,6 @@ init_stuff(PyObject *module_dict) if (!( t=PyDict_New())) return -1; if (!( r=PyRun_String( - "def __init__(self, *args): self.args=args\n\n" "def __str__(self):\n" " a=self.args\n" " a=a and type(a[0]) or '(what)'\n" diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index aa0096a..7e6aedc 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -831,7 +831,7 @@ decoder_feed_buffer(MultibyteStatefulDecoderContext *ctx, { while (buf->inbuf < buf->inbuf_end) { Py_ssize_t inleft, outleft; - int r; + Py_ssize_t r; inleft = (Py_ssize_t)(buf->inbuf_end - buf->inbuf); outleft = (Py_ssize_t)(buf->outbuf_end - buf->outbuf); diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 9ae235a..760ab31 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -3679,6 +3679,13 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp, return NULL; fraction = timestamp - (double)timet; us = (int)round_to_long(fraction * 1e6); + /* If timestamp is less than one microsecond smaller than a + * full second, round up. Otherwise, ValueErrors are raised + * for some floats. */ + if (us == 1000000) { + timet += 1; + us = 0; + } return datetime_from_timet_and_us(cls, f, timet, us, tzinfo); } diff --git a/Modules/expat/expat_config.h b/Modules/expat/expat_config.h new file mode 100644 index 0000000..b8c1639 --- /dev/null +++ b/Modules/expat/expat_config.h @@ -0,0 +1,19 @@ +/* + * Expat configuration for python. This file is not part of the expat + * distribution. + */ +#ifndef EXPAT_CONFIG_H +#define EXPAT_CONFIG_H + +#include <pyconfig.h> +#ifdef WORDS_BIGENDIAN +#define BYTEORDER 4321 +#else +#define BYTEORDER 1234 +#endif + +#define XML_NS 1 +#define XML_DTD 1 +#define XML_CONTEXT_BYTES 1024 + +#endif /* EXPAT_CONFIG_H */ diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index 3372bc9..42d95b7 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -2,10 +2,6 @@ See the file COPYING for copying permission. */ -#include <stddef.h> -#include <string.h> /* memset(), memcpy() */ -#include <assert.h> - #define XML_BUILDING_EXPAT 1 #ifdef COMPILED_FROM_DSP @@ -16,6 +12,10 @@ #include <expat_config.h> #endif /* ndef COMPILED_FROM_DSP */ +#include <stddef.h> +#include <string.h> /* memset(), memcpy() */ +#include <assert.h> + #include "expat.h" #ifdef XML_UNICODE diff --git a/Modules/expat/xmlrole.c b/Modules/expat/xmlrole.c index 1924fcb..2587fdf 100644 --- a/Modules/expat/xmlrole.c +++ b/Modules/expat/xmlrole.c @@ -2,8 +2,6 @@ See the file COPYING for copying permission. */ -#include <stddef.h> - #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) @@ -14,6 +12,8 @@ #endif #endif /* ndef COMPILED_FROM_DSP */ +#include <stddef.h> + #include "expat_external.h" #include "internal.h" #include "xmlrole.h" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c index 160fa40..8b9d997 100644 --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -2,8 +2,6 @@ See the file COPYING for copying permission. */ -#include <stddef.h> - #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) @@ -14,6 +12,8 @@ #endif #endif /* ndef COMPILED_FROM_DSP */ +#include <stddef.h> + #include "expat_external.h" #include "internal.h" #include "xmltok.h" diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index a368494..477af06 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -95,6 +95,7 @@ corresponding to the return value of the fcntl call in the C code."); static PyObject * fcntl_ioctl(PyObject *self, PyObject *args) { +#define IOCTL_BUFSZ 1024 int fd; /* In PyArg_ParseTuple below, use the unsigned int 'I' format for the signed int 'code' variable, because Python turns 0x8000000 @@ -106,7 +107,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) char *str; Py_ssize_t len; int mutate_arg = 1; - char buf[1024]; + char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */ if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl", conv_descriptor, &fd, &code, @@ -114,8 +115,9 @@ fcntl_ioctl(PyObject *self, PyObject *args) char *arg; if (mutate_arg) { - if (len <= sizeof buf) { + if (len <= IOCTL_BUFSZ) { memcpy(buf, str, len); + buf[len] = '\0'; arg = buf; } else { @@ -123,13 +125,14 @@ fcntl_ioctl(PyObject *self, PyObject *args) } } else { - if (len > sizeof buf) { + if (len > IOCTL_BUFSZ) { PyErr_SetString(PyExc_ValueError, "ioctl string arg too long"); return NULL; } else { memcpy(buf, str, len); + buf[len] = '\0'; arg = buf; } } @@ -141,7 +144,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) else { ret = ioctl(fd, code, arg); } - if (mutate_arg && (len < sizeof buf)) { + if (mutate_arg && (len < IOCTL_BUFSZ)) { memcpy(str, buf, len); } if (ret < 0) { @@ -159,12 +162,13 @@ fcntl_ioctl(PyObject *self, PyObject *args) PyErr_Clear(); if (PyArg_ParseTuple(args, "O&Is#:ioctl", conv_descriptor, &fd, &code, &str, &len)) { - if (len > sizeof buf) { + if (len > IOCTL_BUFSZ) { PyErr_SetString(PyExc_ValueError, "ioctl string arg too long"); return NULL; } memcpy(buf, str, len); + buf[len] = '\0'; Py_BEGIN_ALLOW_THREADS ret = ioctl(fd, code, buf); Py_END_ALLOW_THREADS @@ -195,6 +199,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) return NULL; } return PyInt_FromLong((long)ret); +#undef IOCTL_BUFSZ } PyDoc_STRVAR(ioctl_doc, diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 0176d6f..872727d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -75,6 +75,7 @@ static PyObject *delstr = NULL; DEBUG_OBJECTS | \ DEBUG_SAVEALL static int debug; +static PyObject *tmod = NULL; /*-------------------------------------------------------------------------- gc_refs values. @@ -602,7 +603,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) assert(callback != NULL); /* copy-paste of weakrefobject.c's handle_callback() */ - temp = PyObject_CallFunction(callback, "O", wr); + temp = PyObject_CallFunctionObjArgs(callback, wr, NULL); if (temp == NULL) PyErr_WriteUnraisable(callback); else @@ -734,7 +735,6 @@ collect(int generation) PyGC_Head unreachable; /* non-problematic unreachable trash */ PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ PyGC_Head *gc; - static PyObject *tmod = NULL; double t1 = 0.0; if (delstr == NULL) { @@ -743,12 +743,6 @@ collect(int generation) Py_FatalError("gc couldn't allocate \"__del__\""); } - if (tmod == NULL) { - tmod = PyImport_ImportModule("time"); - if (tmod == NULL) - PyErr_Clear(); - } - if (debug & DEBUG_STATS) { if (tmod != NULL) { PyObject *f = PyObject_CallMethod(tmod, "time", NULL); @@ -1233,6 +1227,19 @@ initgc(void) Py_INCREF(garbage); if (PyModule_AddObject(m, "garbage", garbage) < 0) return; + + /* Importing can't be done in collect() because collect() + * can be called via PyGC_Collect() in Py_Finalize(). + * This wouldn't be a problem, except that <initialized> is + * reset to 0 before calling collect which trips up + * the import and triggers an assertion. + */ + if (tmod == NULL) { + tmod = PyImport_ImportModule("time"); + if (tmod == NULL) + PyErr_Clear(); + } + #define ADD_INT(NAME) if (PyModule_AddIntConstant(m, #NAME, NAME) < 0) return ADD_INT(DEBUG_STATS); ADD_INT(DEBUG_COLLECTABLE); diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index 12d33dd..e5b9f47 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -84,12 +84,18 @@ mkgrent(struct group *p) } static PyObject * -grp_getgrgid(PyObject *self, PyObject *args) +grp_getgrgid(PyObject *self, PyObject *pyo_id) { + PyObject *py_int_id; unsigned int gid; struct group *p; - if (!PyArg_ParseTuple(args, "I:getgrgid", &gid)) - return NULL; + + py_int_id = PyNumber_Int(pyo_id); + if (!py_int_id) + return NULL; + gid = PyInt_AS_LONG(py_int_id); + Py_DECREF(py_int_id); + if ((p = getgrgid(gid)) == NULL) { PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %d", gid); return NULL; @@ -98,27 +104,33 @@ grp_getgrgid(PyObject *self, PyObject *args) } static PyObject * -grp_getgrnam(PyObject *self, PyObject *args) +grp_getgrnam(PyObject *self, PyObject *pyo_name) { + PyObject *py_str_name; char *name; struct group *p; - if (!PyArg_ParseTuple(args, "s:getgrnam", &name)) - return NULL; + + py_str_name = PyObject_Str(pyo_name); + if (!py_str_name) + return NULL; + name = PyString_AS_STRING(py_str_name); + if ((p = getgrnam(name)) == NULL) { PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name); + Py_DECREF(py_str_name); return NULL; } + + Py_DECREF(py_str_name); return mkgrent(p); } static PyObject * -grp_getgrall(PyObject *self, PyObject *args) +grp_getgrall(PyObject *self, PyObject *ignore) { PyObject *d; struct group *p; - if (!PyArg_ParseTuple(args, ":getgrall")) - return NULL; if ((d = PyList_New(0)) == NULL) return NULL; setgrent(); @@ -136,15 +148,15 @@ grp_getgrall(PyObject *self, PyObject *args) } static PyMethodDef grp_methods[] = { - {"getgrgid", grp_getgrgid, METH_VARARGS, + {"getgrgid", grp_getgrgid, METH_O, "getgrgid(id) -> tuple\n\ Return the group database entry for the given numeric group ID. If\n\ id is not valid, raise KeyError."}, - {"getgrnam", grp_getgrnam, METH_VARARGS, + {"getgrnam", grp_getgrnam, METH_O, "getgrnam(name) -> tuple\n\ Return the group database entry for the given group name. If\n\ name is not valid, raise KeyError."}, - {"getgrall", grp_getgrall, METH_VARARGS, + {"getgrall", grp_getgrall, METH_NOARGS, "getgrall() -> list of tuples\n\ Return a list of all available group entries, in arbitrary order."}, {NULL, NULL} /* sentinel */ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 94617a9..86b1bbf 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1093,10 +1093,10 @@ static PyTypeObject takewhile_type = { typedef struct { PyObject_HEAD PyObject *it; - long next; - long stop; - long step; - long cnt; + Py_ssize_t next; + Py_ssize_t stop; + Py_ssize_t step; + Py_ssize_t cnt; } isliceobject; static PyTypeObject islice_type; @@ -1105,7 +1105,7 @@ static PyObject * islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *seq; - long start=0, stop=-1, step=1; + Py_ssize_t start=0, stop=-1, step=1; PyObject *it, *a1=NULL, *a2=NULL, *a3=NULL; Py_ssize_t numargs; isliceobject *lz; @@ -1119,7 +1119,7 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) numargs = PyTuple_Size(args); if (numargs == 2) { if (a1 != Py_None) { - stop = PyInt_AsLong(a1); + stop = PyInt_AsSsize_t(a1); if (stop == -1) { if (PyErr_Occurred()) PyErr_Clear(); @@ -1130,11 +1130,11 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } else { if (a1 != Py_None) - start = PyInt_AsLong(a1); + start = PyInt_AsSsize_t(a1); if (start == -1 && PyErr_Occurred()) PyErr_Clear(); if (a2 != Py_None) { - stop = PyInt_AsLong(a2); + stop = PyInt_AsSsize_t(a2); if (stop == -1) { if (PyErr_Occurred()) PyErr_Clear(); @@ -1152,7 +1152,7 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (a3 != NULL) { if (a3 != Py_None) - step = PyInt_AsLong(a3); + step = PyInt_AsSsize_t(a3); if (step == -1 && PyErr_Occurred()) PyErr_Clear(); } @@ -1202,7 +1202,7 @@ islice_next(isliceobject *lz) { PyObject *item; PyObject *it = lz->it; - long oldnext; + Py_ssize_t oldnext; PyObject *(*iternext)(PyObject *); assert(PyIter_Check(it)); @@ -1600,8 +1600,8 @@ static PyTypeObject imap_type = { typedef struct { PyObject_HEAD - Py_ssize_t tuplesize; - long iternum; /* which iterator is active */ + Py_ssize_t tuplesize; + Py_ssize_t iternum; /* which iterator is active */ PyObject *ittuple; /* tuple of iterators */ } chainobject; @@ -1612,7 +1612,7 @@ chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { chainobject *lz; Py_ssize_t tuplesize = PySequence_Length(args); - int i; + Py_ssize_t i; PyObject *ittuple; if (!_PyArg_NoKeywords("chain()", kwds)) @@ -1621,7 +1621,7 @@ chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* obtain iterators */ assert(PyTuple_Check(args)); ittuple = PyTuple_New(tuplesize); - if(ittuple == NULL) + if (ittuple == NULL) return NULL; for (i=0; i < tuplesize; ++i) { PyObject *item = PyTuple_GET_ITEM(args, i); @@ -1629,7 +1629,7 @@ chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (it == NULL) { if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, - "chain argument #%d must support iteration", + "chain argument #%zd must support iteration", i+1); Py_DECREF(ittuple); return NULL; @@ -2033,7 +2033,7 @@ static PyTypeObject ifilterfalse_type = { typedef struct { PyObject_HEAD - long cnt; + Py_ssize_t cnt; } countobject; static PyTypeObject count_type; @@ -2042,12 +2042,12 @@ static PyObject * count_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { countobject *lz; - long cnt = 0; + Py_ssize_t cnt = 0; if (!_PyArg_NoKeywords("count()", kwds)) return NULL; - if (!PyArg_ParseTuple(args, "|l:count", &cnt)) + if (!PyArg_ParseTuple(args, "|n:count", &cnt)) return NULL; /* create countobject structure */ @@ -2062,13 +2062,13 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * count_next(countobject *lz) { - return PyInt_FromLong(lz->cnt++); + return PyInt_FromSize_t(lz->cnt++); } static PyObject * count_repr(countobject *lz) { - return PyString_FromFormat("count(%ld)", lz->cnt); + return PyString_FromFormat("count(%zd)", lz->cnt); } PyDoc_STRVAR(count_doc, @@ -2138,7 +2138,7 @@ static PyObject * izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { izipobject *lz; - int i; + Py_ssize_t i; PyObject *ittuple; /* tuple of iterators */ PyObject *result; Py_ssize_t tuplesize = PySequence_Length(args); @@ -2151,7 +2151,7 @@ izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* obtain iterators */ ittuple = PyTuple_New(tuplesize); - if(ittuple == NULL) + if (ittuple == NULL) return NULL; for (i=0; i < tuplesize; ++i) { PyObject *item = PyTuple_GET_ITEM(args, i); @@ -2159,7 +2159,7 @@ izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (it == NULL) { if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, - "izip argument #%d must support iteration", + "izip argument #%zd must support iteration", i+1); Py_DECREF(ittuple); return NULL; @@ -2212,7 +2212,7 @@ izip_traverse(izipobject *lz, visitproc visit, void *arg) static PyObject * izip_next(izipobject *lz) { - int i; + Py_ssize_t i; Py_ssize_t tuplesize = lz->tuplesize; PyObject *result = lz->result; PyObject *it; @@ -2314,7 +2314,7 @@ static PyTypeObject izip_type = { typedef struct { PyObject_HEAD PyObject *element; - long cnt; + Py_ssize_t cnt; } repeatobject; static PyTypeObject repeat_type; @@ -2324,12 +2324,12 @@ repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { repeatobject *ro; PyObject *element; - long cnt = -1; + Py_ssize_t cnt = -1; if (!_PyArg_NoKeywords("repeat()", kwds)) return NULL; - if (!PyArg_ParseTuple(args, "O|l:repeat", &element, &cnt)) + if (!PyArg_ParseTuple(args, "O|n:repeat", &element, &cnt)) return NULL; if (PyTuple_Size(args) == 2 && cnt < 0) @@ -2383,7 +2383,7 @@ repeat_repr(repeatobject *ro) result = PyString_FromFormat("repeat(%s)", PyString_AS_STRING(objrepr)); else - result = PyString_FromFormat("repeat(%s, %ld)", + result = PyString_FromFormat("repeat(%s, %zd)", PyString_AS_STRING(objrepr), ro->cnt); Py_DECREF(objrepr); return result; @@ -2396,7 +2396,7 @@ repeat_len(repeatobject *ro) PyErr_SetString(PyExc_TypeError, "len() of unsized object"); return NULL; } - return PyInt_FromLong(ro->cnt); + return PyInt_FromSize_t(ro->cnt); } PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); diff --git a/Modules/main.c b/Modules/main.c index 7326a27..23a760f 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -9,8 +9,10 @@ #endif #if defined(MS_WINDOWS) || defined(__CYGWIN__) +#ifdef HAVE_FCNTL_H #include <fcntl.h> #endif +#endif #if (defined(PYOS_OS2) && !defined(PYCC_GCC)) || defined(MS_WINDOWS) #define PYTHONHOMEHELP "<prefix>\\lib" diff --git a/Modules/operator.c b/Modules/operator.c index cbce16e..bf3def4 100644 --- a/Modules/operator.c +++ b/Modules/operator.c @@ -48,6 +48,12 @@ used for special class methods; variants without leading and trailing\n\ if(-1 == (r=AOP(a1,a2))) return NULL; \ return PyInt_FromLong(r); } +#define spamn2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \ + PyObject *a1, *a2; Py_ssize_t r; \ + if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \ + if(-1 == (r=AOP(a1,a2))) return NULL; \ + return PyInt_FromSsize_t(r); } + #define spami2b(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \ PyObject *a1, *a2; long r; \ if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \ @@ -97,8 +103,8 @@ spam2(op_iconcat , PySequence_InPlaceConcat) spamoi(op_irepeat , PySequence_InPlaceRepeat) spami2b(op_contains , PySequence_Contains) spami2b(sequenceIncludes, PySequence_Contains) -spami2(indexOf , PySequence_Index) -spami2(countOf , PySequence_Count) +spamn2(indexOf , PySequence_Index) +spamn2(countOf , PySequence_Count) spami(isMappingType , PyMapping_Check) spam2(op_getitem , PyObject_GetItem) spam2n(op_delitem , PyObject_DelItem) diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index c9edae6..e33197e 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -3267,8 +3267,8 @@ initparser(void) && (pickler != NULL)) { PyObject *res; - res = PyObject_CallFunction(func, "OOO", &PyST_Type, pickler, - pickle_constructor); + res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler, + pickle_constructor, NULL); Py_XDECREF(res); } Py_XDECREF(func); diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index b51ba5d..7f0a261 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -13,6 +13,18 @@ /* See also ../Dos/dosmodule.c */ +#ifdef __APPLE__ + /* + * Step 1 of support for weak-linking a number of symbols existing on + * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block + * at the end of this file for more information. + */ +# pragma weak lchown +# pragma weak statvfs +# pragma weak fstatvfs + +#endif /* __APPLE__ */ + #define PY_SSIZE_T_CLEAN #include "Python.h" @@ -250,7 +262,11 @@ extern int lstat(const char *, struct stat *); #endif /* OS2 */ #ifndef MAXPATHLEN +#if defined(PATH_MAX) && PATH_MAX > 1024 +#define MAXPATHLEN PATH_MAX +#else #define MAXPATHLEN 1024 +#endif #endif /* MAXPATHLEN */ #ifdef UNION_WAIT @@ -442,21 +458,29 @@ win32_error_unicode(char* function, Py_UNICODE* filename) static PyObject *_PyUnicode_FromFileSystemEncodedObject(register PyObject *obj) { - /* XXX Perhaps we should make this API an alias of - PyObject_Unicode() instead ?! */ - if (PyUnicode_CheckExact(obj)) { - Py_INCREF(obj); - return obj; - } - if (PyUnicode_Check(obj)) { +} + +/* Function suitable for O& conversion */ +static int +convert_to_unicode(PyObject *arg, void* _param) +{ + PyObject **param = (PyObject**)_param; + if (PyUnicode_CheckExact(arg)) { + Py_INCREF(arg); + *param = arg; + } + else if (PyUnicode_Check(arg)) { /* For a Unicode subtype that's not a Unicode object, return a true Unicode object with the same data. */ - return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(obj), - PyUnicode_GET_SIZE(obj)); + *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(arg), + PyUnicode_GET_SIZE(arg)); + return *param != NULL; } - return PyUnicode_FromEncodedObject(obj, - Py_FileSystemDefaultEncoding, - "strict"); + else + *param = PyUnicode_FromEncodedObject(arg, + Py_FileSystemDefaultEncoding, + "strict"); + return (*param) != NULL; } #endif /* Py_WIN_WIDE_FILENAMES */ @@ -573,35 +597,10 @@ unicode_file_names(void) #endif static PyObject * -posix_1str(PyObject *args, char *format, int (*func)(const char*), - char *wformat, int (*wfunc)(const Py_UNICODE*)) +posix_1str(PyObject *args, char *format, int (*func)(const char*)) { char *path1 = NULL; int res; -#ifdef Py_WIN_WIDE_FILENAMES - if (unicode_file_names()) { - PyUnicodeObject *po; - if (PyArg_ParseTuple(args, wformat, &po)) { - Py_BEGIN_ALLOW_THREADS - /* PyUnicode_AS_UNICODE OK without thread - lock as it is a simple dereference. */ - res = (*wfunc)(PyUnicode_AS_UNICODE(po)); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error_with_unicode_filename(PyUnicode_AS_UNICODE(po)); - Py_INCREF(Py_None); - return Py_None; - } - /* Drop the argument parsing error as narrow - strings are also valid. */ - PyErr_Clear(); - } -#else - /* Platforms that don't support Unicode filenames - shouldn't be passing these extra params */ - assert(wformat==NULL && wfunc == NULL); -#endif - if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1)) return NULL; @@ -618,52 +617,10 @@ posix_1str(PyObject *args, char *format, int (*func)(const char*), static PyObject * posix_2str(PyObject *args, char *format, - int (*func)(const char *, const char *), - char *wformat, - int (*wfunc)(const Py_UNICODE *, const Py_UNICODE *)) + int (*func)(const char *, const char *)) { char *path1 = NULL, *path2 = NULL; int res; -#ifdef Py_WIN_WIDE_FILENAMES - if (unicode_file_names()) { - PyObject *po1; - PyObject *po2; - if (PyArg_ParseTuple(args, wformat, &po1, &po2)) { - if (PyUnicode_Check(po1) || PyUnicode_Check(po2)) { - PyObject *wpath1; - PyObject *wpath2; - wpath1 = _PyUnicode_FromFileSystemEncodedObject(po1); - wpath2 = _PyUnicode_FromFileSystemEncodedObject(po2); - if (!wpath1 || !wpath2) { - Py_XDECREF(wpath1); - Py_XDECREF(wpath2); - return NULL; - } - Py_BEGIN_ALLOW_THREADS - /* PyUnicode_AS_UNICODE OK without thread - lock as it is a simple dereference. */ - res = (*wfunc)(PyUnicode_AS_UNICODE(wpath1), - PyUnicode_AS_UNICODE(wpath2)); - Py_END_ALLOW_THREADS - Py_XDECREF(wpath1); - Py_XDECREF(wpath2); - if (res != 0) - return posix_error(); - Py_INCREF(Py_None); - return Py_None; - } - /* Else flow through as neither is Unicode. */ - } - /* Drop the argument parsing error as narrow - strings are also valid. */ - PyErr_Clear(); - } -#else - /* Platforms that don't support Unicode filenames - shouldn't be passing these extra params */ - assert(wformat==NULL && wfunc == NULL); -#endif - if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1, Py_FileSystemDefaultEncoding, &path2)) @@ -680,6 +637,101 @@ posix_2str(PyObject *args, return Py_None; } +#ifdef Py_WIN_WIDE_FILENAMES +static PyObject* +win32_1str(PyObject* args, char* func, + char* format, BOOL (__stdcall *funcA)(LPCSTR), + char* wformat, BOOL (__stdcall *funcW)(LPWSTR)) +{ + PyObject *uni; + char *ansi; + BOOL result; + if (unicode_file_names()) { + if (!PyArg_ParseTuple(args, wformat, &uni)) + PyErr_Clear(); + else { + Py_BEGIN_ALLOW_THREADS + result = funcW(PyUnicode_AsUnicode(uni)); + Py_END_ALLOW_THREADS + if (!result) + return win32_error_unicode(func, PyUnicode_AsUnicode(uni)); + Py_INCREF(Py_None); + return Py_None; + } + } + if (!PyArg_ParseTuple(args, format, &ansi)) + return NULL; + Py_BEGIN_ALLOW_THREADS + result = funcA(ansi); + Py_END_ALLOW_THREADS + if (!result) + return win32_error(func, ansi); + Py_INCREF(Py_None); + return Py_None; + +} + +/* This is a reimplementation of the C library's chdir function, + but one that produces Win32 errors instead of DOS error codes. + chdir is essentially a wrapper around SetCurrentDirectory; however, + it also needs to set "magic" environment variables indicating + the per-drive current directory, which are of the form =<drive>: */ +BOOL __stdcall +win32_chdir(LPCSTR path) +{ + char new_path[MAX_PATH+1]; + int result; + char env[4] = "=x:"; + + if(!SetCurrentDirectoryA(path)) + return FALSE; + result = GetCurrentDirectoryA(MAX_PATH+1, new_path); + if (!result) + return FALSE; + /* In the ANSI API, there should not be any paths longer + than MAX_PATH. */ + assert(result <= MAX_PATH+1); + if (strncmp(new_path, "\\\\", 2) == 0 || + strncmp(new_path, "//", 2) == 0) + /* UNC path, nothing to do. */ + return TRUE; + env[1] = new_path[0]; + return SetEnvironmentVariableA(env, new_path); +} + +/* The Unicode version differs from the ANSI version + since the current directory might exceed MAX_PATH characters */ +BOOL __stdcall +win32_wchdir(LPCWSTR path) +{ + wchar_t _new_path[MAX_PATH+1], *new_path = _new_path; + int result; + wchar_t env[4] = L"=x:"; + + if(!SetCurrentDirectoryW(path)) + return FALSE; + result = GetCurrentDirectoryW(MAX_PATH+1, new_path); + if (!result) + return FALSE; + if (result > MAX_PATH+1) { + new_path = malloc(result); + if (!new_path) { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + } + if (wcsncmp(new_path, L"\\\\", 2) == 0 || + wcsncmp(new_path, L"//", 2) == 0) + /* UNC path, nothing to do. */ + return TRUE; + env[1] = new_path[0]; + result = SetEnvironmentVariableW(env, new_path); + if (new_path != _new_path) + free(new_path); + return result; +} +#endif + #ifdef MS_WINDOWS /* The CRT of Windows has a number of flaws wrt. its stat() implementation: - time stamps are restricted to second resolution @@ -711,13 +763,26 @@ static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 an static void FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, int *time_out, int* nsec_out) { - /* XXX endianness */ - __int64 in = *(__int64*)in_ptr; + /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */ + /* Cannot simply cast and dereference in_ptr, + since it might not be aligned properly */ + __int64 in; + memcpy(&in, in_ptr, sizeof(in)); *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */ /* XXX Win32 supports time stamps past 2038; we currently don't */ *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, int); } +static void +time_t_to_FILE_TIME(int time_in, int nsec_in, FILETIME *out_ptr) +{ + /* XXX endianness */ + __int64 out; + out = time_in + secs_between_epochs; + out = out * 10000000 + nsec_in; + memcpy(out_ptr, &out, sizeof(out)); +} + /* Below, we *know* that ugo+r is 0444 */ #if _S_IREAD != 0400 #error Unsupported C library @@ -1292,24 +1357,39 @@ posix_access(PyObject *self, PyObject *args) { char *path; int mode; - int res; - + #ifdef Py_WIN_WIDE_FILENAMES + DWORD attr; if (unicode_file_names()) { PyUnicodeObject *po; if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) { Py_BEGIN_ALLOW_THREADS /* PyUnicode_AS_UNICODE OK without thread lock as it is a simple dereference. */ - res = _waccess(PyUnicode_AS_UNICODE(po), mode); + attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po)); Py_END_ALLOW_THREADS - return PyBool_FromLong(res == 0); + goto finish; } /* Drop the argument parsing error as narrow strings are also valid. */ PyErr_Clear(); } -#endif + if (!PyArg_ParseTuple(args, "eti:access", + Py_FileSystemDefaultEncoding, &path, &mode)) + return 0; + Py_BEGIN_ALLOW_THREADS + attr = GetFileAttributesA(path); + Py_END_ALLOW_THREADS + PyMem_Free(path); +finish: + if (attr == 0xFFFFFFFF) + /* File does not exist, or cannot read attributes */ + return PyBool_FromLong(0); + /* Access is possible if either write access wasn't requested, or + the file isn't read-only. */ + return PyBool_FromLong(!(mode & 2) || !(attr && FILE_ATTRIBUTE_READONLY)); +#else + int res; if (!PyArg_ParseTuple(args, "eti:access", Py_FileSystemDefaultEncoding, &path, &mode)) return NULL; @@ -1318,6 +1398,7 @@ posix_access(PyObject *self, PyObject *args) Py_END_ALLOW_THREADS PyMem_Free(path); return PyBool_FromLong(res == 0); +#endif } #ifndef F_OK @@ -1394,14 +1475,13 @@ static PyObject * posix_chdir(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - return posix_1str(args, "et:chdir", chdir, "U:chdir", _wchdir); + return win32_1str(args, "chdir", "s:chdir", win32_chdir, "U:chdir", win32_wchdir); #elif defined(PYOS_OS2) && defined(PYCC_GCC) - return posix_1str(args, "et:chdir", _chdir2, NULL, NULL); + return posix_1str(args, "et:chdir", _chdir2); #elif defined(__VMS) - return posix_1str(args, "et:chdir", (int (*)(const char *))chdir, - NULL, NULL); + return posix_1str(args, "et:chdir", (int (*)(const char *))chdir); #else - return posix_1str(args, "et:chdir", chdir, NULL, NULL); + return posix_1str(args, "et:chdir", chdir); #endif } @@ -1430,14 +1510,24 @@ posix_chmod(PyObject *self, PyObject *args) int i; int res; #ifdef Py_WIN_WIDE_FILENAMES + DWORD attr; if (unicode_file_names()) { PyUnicodeObject *po; if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) { Py_BEGIN_ALLOW_THREADS - res = _wchmod(PyUnicode_AS_UNICODE(po), i); + attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po)); + if (attr != 0xFFFFFFFF) { + if (i & _S_IWRITE) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr); + } + else + res = 0; Py_END_ALLOW_THREADS - if (res < 0) - return posix_error_with_unicode_filename( + if (!res) + return win32_error_unicode("chmod", PyUnicode_AS_UNICODE(po)); Py_INCREF(Py_None); return Py_None; @@ -1446,7 +1536,30 @@ posix_chmod(PyObject *self, PyObject *args) are also valid. */ PyErr_Clear(); } -#endif /* Py_WIN_WIDE_FILENAMES */ + if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding, + &path, &i)) + return NULL; + Py_BEGIN_ALLOW_THREADS + attr = GetFileAttributesA(path); + if (attr != 0xFFFFFFFF) { + if (i & _S_IWRITE) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + res = SetFileAttributesA(path, attr); + } + else + res = 0; + Py_END_ALLOW_THREADS + if (!res) { + win32_error("chmod", path); + PyMem_Free(path); + return NULL; + } + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +#else /* Py_WIN_WIDE_FILENAMES */ if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding, &path, &i)) return NULL; @@ -1458,6 +1571,7 @@ posix_chmod(PyObject *self, PyObject *args) PyMem_Free(path); Py_INCREF(Py_None); return Py_None; +#endif } @@ -1469,7 +1583,7 @@ Change root directory to path."); static PyObject * posix_chroot(PyObject *self, PyObject *args) { - return posix_1str(args, "et:chroot", chroot, NULL, NULL); + return posix_1str(args, "et:chroot", chroot); } #endif @@ -1593,15 +1707,33 @@ posix_getcwdu(PyObject *self, PyObject *noargs) char *res; #ifdef Py_WIN_WIDE_FILENAMES + DWORD len; if (unicode_file_names()) { - wchar_t *wres; wchar_t wbuf[1026]; + wchar_t *wbuf2 = wbuf; + PyObject *resobj; Py_BEGIN_ALLOW_THREADS - wres = _wgetcwd(wbuf, sizeof wbuf/ sizeof wbuf[0]); + len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf); + /* If the buffer is large enough, len does not include the + terminating \0. If the buffer is too small, len includes + the space needed for the terminator. */ + if (len >= sizeof wbuf/ sizeof wbuf[0]) { + wbuf2 = malloc(len * sizeof(wchar_t)); + if (wbuf2) + len = GetCurrentDirectoryW(len, wbuf2); + } Py_END_ALLOW_THREADS - if (wres == NULL) - return posix_error(); - return PyUnicode_FromWideChar(wbuf, wcslen(wbuf)); + if (!wbuf2) { + PyErr_NoMemory(); + return NULL; + } + if (!len) { + if (wbuf2 != wbuf) free(wbuf2); + return win32_error("getcwdu", NULL); + } + resobj = PyUnicode_FromWideChar(wbuf2, len); + if (wbuf2 != wbuf) free(wbuf2); + return resobj; } #endif @@ -1628,7 +1760,7 @@ Create a hard link to a file."); static PyObject * posix_link(PyObject *self, PyObject *args) { - return posix_2str(args, "etet:link", link, NULL, NULL); + return posix_2str(args, "etet:link", link); } #endif /* HAVE_LINK */ @@ -1653,37 +1785,46 @@ posix_listdir(PyObject *self, PyObject *args) HANDLE hFindFile; BOOL result; WIN32_FIND_DATA FileData; - /* MAX_PATH characters could mean a bigger encoded string */ - char namebuf[MAX_PATH*2+5]; + char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */ char *bufptr = namebuf; - Py_ssize_t len = sizeof(namebuf)/sizeof(namebuf[0]); + Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */ #ifdef Py_WIN_WIDE_FILENAMES /* If on wide-character-capable OS see if argument is Unicode and if so use wide API. */ if (unicode_file_names()) { - PyUnicodeObject *po; + PyObject *po; if (PyArg_ParseTuple(args, "U:listdir", &po)) { WIN32_FIND_DATAW wFileData; - Py_UNICODE wnamebuf[MAX_PATH*2+5]; + Py_UNICODE *wnamebuf; Py_UNICODE wch; - wcsncpy(wnamebuf, PyUnicode_AS_UNICODE(po), MAX_PATH); - wnamebuf[MAX_PATH] = L'\0'; - len = wcslen(wnamebuf); - wch = (len > 0) ? wnamebuf[len-1] : L'\0'; + /* Overallocate for \\*.*\0 */ + len = PyUnicode_GET_SIZE(po); + wnamebuf = malloc((len + 5) * sizeof(wchar_t)); + if (!wnamebuf) { + PyErr_NoMemory(); + return NULL; + } + wcscpy(wnamebuf, PyUnicode_AS_UNICODE(po)); + wch = len > 0 ? wnamebuf[len-1] : '\0'; if (wch != L'/' && wch != L'\\' && wch != L':') - wnamebuf[len++] = L'/'; + wnamebuf[len++] = L'\\'; wcscpy(wnamebuf + len, L"*.*"); - if ((d = PyList_New(0)) == NULL) + if ((d = PyList_New(0)) == NULL) { + free(wnamebuf); return NULL; + } hFindFile = FindFirstFileW(wnamebuf, &wFileData); if (hFindFile == INVALID_HANDLE_VALUE) { - errno = GetLastError(); - if (errno == ERROR_FILE_NOT_FOUND) { + int error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) { + free(wnamebuf); return d; } Py_DECREF(d); - return win32_error_unicode("FindFirstFileW", wnamebuf); + win32_error_unicode("FindFirstFileW", wnamebuf); + free(wnamebuf); + return NULL; } do { /* Skip over . and .. */ @@ -1710,8 +1851,11 @@ posix_listdir(PyObject *self, PyObject *args) if (FindClose(hFindFile) == FALSE) { Py_DECREF(d); - return win32_error_unicode("FindClose", wnamebuf); + win32_error_unicode("FindClose", wnamebuf); + free(wnamebuf); + return NULL; } + free(wnamebuf); return d; } /* Drop the argument parsing error as narrow strings @@ -1735,8 +1879,8 @@ posix_listdir(PyObject *self, PyObject *args) hFindFile = FindFirstFile(namebuf, &FileData); if (hFindFile == INVALID_HANDLE_VALUE) { - errno = GetLastError(); - if (errno == ERROR_FILE_NOT_FOUND) + int error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) return d; Py_DECREF(d); return win32_error("FindFirstFile", namebuf); @@ -1982,10 +2126,10 @@ posix_mkdir(PyObject *self, PyObject *args) Py_BEGIN_ALLOW_THREADS /* PyUnicode_AS_UNICODE OK without thread lock as it is a simple dereference. */ - res = _wmkdir(PyUnicode_AS_UNICODE(po)); + res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL); Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); + if (!res) + return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po)); Py_INCREF(Py_None); return Py_None; } @@ -1993,13 +2137,29 @@ posix_mkdir(PyObject *self, PyObject *args) are also valid. */ PyErr_Clear(); } -#endif + if (!PyArg_ParseTuple(args, "et|i:mkdir", + Py_FileSystemDefaultEncoding, &path, &mode)) + return NULL; + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread lock as + it is a simple dereference. */ + res = CreateDirectoryA(path, NULL); + Py_END_ALLOW_THREADS + if (!res) { + win32_error("mkdir", path); + PyMem_Free(path); + return NULL; + } + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +#else if (!PyArg_ParseTuple(args, "et|i:mkdir", Py_FileSystemDefaultEncoding, &path, &mode)) return NULL; Py_BEGIN_ALLOW_THREADS -#if ( defined(__WATCOMC__) || defined(_MSC_VER) || defined(PYCC_VACPP) ) && !defined(__QNX__) +#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__) res = mkdir(path); #else res = mkdir(path, mode); @@ -2010,6 +2170,7 @@ posix_mkdir(PyObject *self, PyObject *args) PyMem_Free(path); Py_INCREF(Py_None); return Py_None; +#endif } @@ -2055,7 +2216,6 @@ posix_nice(PyObject *self, PyObject *args) } #endif /* HAVE_NICE */ - PyDoc_STRVAR(posix_rename__doc__, "rename(old, new)\n\n\ Rename a file or directory."); @@ -2064,9 +2224,38 @@ static PyObject * posix_rename(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - return posix_2str(args, "etet:rename", rename, "OO:rename", _wrename); + PyObject *o1, *o2; + char *p1, *p2; + BOOL result; + if (unicode_file_names()) { + if (!PyArg_ParseTuple(args, "O&O&:rename", + convert_to_unicode, &o1, + convert_to_unicode, &o2)) + PyErr_Clear(); + else { + Py_BEGIN_ALLOW_THREADS + result = MoveFileW(PyUnicode_AsUnicode(o1), + PyUnicode_AsUnicode(o2)); + Py_END_ALLOW_THREADS + Py_DECREF(o1); + Py_DECREF(o2); + if (!result) + return win32_error("rename", NULL); + Py_INCREF(Py_None); + return Py_None; + } + } + if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2)) + return NULL; + Py_BEGIN_ALLOW_THREADS + result = MoveFileA(p1, p2); + Py_END_ALLOW_THREADS + if (!result) + return win32_error("rename", NULL); + Py_INCREF(Py_None); + return Py_None; #else - return posix_2str(args, "etet:rename", rename, NULL, NULL); + return posix_2str(args, "etet:rename", rename); #endif } @@ -2079,9 +2268,9 @@ static PyObject * posix_rmdir(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - return posix_1str(args, "et:rmdir", rmdir, "U:rmdir", _wrmdir); + return win32_1str(args, "rmdir", "s:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW); #else - return posix_1str(args, "et:rmdir", rmdir, NULL, NULL); + return posix_1str(args, "et:rmdir", rmdir); #endif } @@ -2150,9 +2339,9 @@ static PyObject * posix_unlink(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - return posix_1str(args, "et:remove", unlink, "U:remove", _wunlink); + return win32_1str(args, "remove", "s:remove", DeleteFileA, "U:remove", DeleteFileW); #else - return posix_1str(args, "et:remove", unlink, NULL, NULL); + return posix_1str(args, "et:remove", unlink); #endif } @@ -2212,7 +2401,7 @@ extract_time(PyObject *t, long* sec, long* usec) } PyDoc_STRVAR(posix_utime__doc__, -"utime(path, (atime, utime))\n\ +"utime(path, (atime, mtime))\n\ utime(path, None)\n\n\ Set the access and modified time of the file to the given values. If the\n\ second form is used, set the access and modified times to the current time."); @@ -2220,6 +2409,84 @@ second form is used, set the access and modified times to the current time."); static PyObject * posix_utime(PyObject *self, PyObject *args) { +#ifdef Py_WIN_WIDE_FILENAMES + PyObject *arg; + PyUnicodeObject *obwpath; + wchar_t *wpath = NULL; + char *apath = NULL; + HANDLE hFile; + long atimesec, mtimesec, ausec, musec; + FILETIME atime, mtime; + PyObject *result = NULL; + + if (unicode_file_names()) { + if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) { + wpath = PyUnicode_AS_UNICODE(obwpath); + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0, + NULL, OPEN_EXISTING, 0, NULL); + Py_END_ALLOW_THREADS + if (hFile == INVALID_HANDLE_VALUE) + return win32_error_unicode("utime", wpath); + } else + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + if (!wpath) { + if (!PyArg_ParseTuple(args, "etO:utime", + Py_FileSystemDefaultEncoding, &apath, &arg)) + return NULL; + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0, + NULL, OPEN_EXISTING, 0, NULL); + Py_END_ALLOW_THREADS + if (hFile == INVALID_HANDLE_VALUE) { + win32_error("utime", apath); + PyMem_Free(apath); + return NULL; + } + PyMem_Free(apath); + } + + if (arg == Py_None) { + SYSTEMTIME now; + GetSystemTime(&now); + if (!SystemTimeToFileTime(&now, &mtime) || + !SystemTimeToFileTime(&now, &atime)) { + win32_error("utime", NULL); + goto done; + } + } + else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) { + PyErr_SetString(PyExc_TypeError, + "utime() arg 2 must be a tuple (atime, mtime)"); + goto done; + } + else { + if (extract_time(PyTuple_GET_ITEM(arg, 0), + &atimesec, &ausec) == -1) + goto done; + time_t_to_FILE_TIME(atimesec, ausec, &atime); + if (extract_time(PyTuple_GET_ITEM(arg, 1), + &mtimesec, &musec) == -1) + goto done; + time_t_to_FILE_TIME(mtimesec, musec, &mtime); + } + if (!SetFileTime(hFile, NULL, &atime, &mtime)) { + /* Avoid putting the file name into the error here, + as that may confuse the user into believing that + something is wrong with the file, when it also + could be the time stamp that gives a problem. */ + win32_error("utime", NULL); + } + Py_INCREF(Py_None); + result = Py_None; +done: + CloseHandle(hFile); + return result; +#else /* Py_WIN_WIDE_FILENAMES */ + char *path = NULL; long atime, mtime, ausec, musec; int res; @@ -2242,33 +2509,13 @@ posix_utime(PyObject *self, PyObject *args) #define UTIME_ARG buf #endif /* HAVE_UTIMES */ - int have_unicode_filename = 0; -#ifdef Py_WIN_WIDE_FILENAMES - PyUnicodeObject *obwpath; - wchar_t *wpath; - if (unicode_file_names()) { - if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) { - wpath = PyUnicode_AS_UNICODE(obwpath); - have_unicode_filename = 1; - } else - /* Drop the argument parsing error as narrow strings - are also valid. */ - PyErr_Clear(); - } -#endif /* Py_WIN_WIDE_FILENAMES */ - if (!have_unicode_filename && \ - !PyArg_ParseTuple(args, "etO:utime", + if (!PyArg_ParseTuple(args, "etO:utime", Py_FileSystemDefaultEncoding, &path, &arg)) return NULL; if (arg == Py_None) { /* optional time values not given */ Py_BEGIN_ALLOW_THREADS -#ifdef Py_WIN_WIDE_FILENAMES - if (have_unicode_filename) - res = _wutime(wpath, NULL); - else -#endif /* Py_WIN_WIDE_FILENAMES */ res = utime(path, NULL); Py_END_ALLOW_THREADS } @@ -2299,23 +2546,11 @@ posix_utime(PyObject *self, PyObject *args) Py_END_ALLOW_THREADS #else Py_BEGIN_ALLOW_THREADS -#ifdef Py_WIN_WIDE_FILENAMES - if (have_unicode_filename) - /* utime is OK with utimbuf, but _wutime insists - on _utimbuf (the msvc headers assert the - underscore version is ansi) */ - res = _wutime(wpath, (struct _utimbuf *)UTIME_ARG); - else -#endif /* Py_WIN_WIDE_FILENAMES */ res = utime(path, UTIME_ARG); Py_END_ALLOW_THREADS #endif /* HAVE_UTIMES */ } if (res < 0) { -#ifdef Py_WIN_WIDE_FILENAMES - if (have_unicode_filename) - return posix_error_with_unicode_filename(wpath); -#endif /* Py_WIN_WIDE_FILENAMES */ return posix_error_with_allocated_filename(path); } PyMem_Free(path); @@ -2324,6 +2559,7 @@ posix_utime(PyObject *self, PyObject *args) #undef UTIME_ARG #undef ATIME #undef MTIME +#endif /* Py_WIN_WIDE_FILENAMES */ } @@ -2440,7 +2676,7 @@ posix_execve(PyObject *self, PyObject *args) PyObject *key, *val, *keys=NULL, *vals=NULL; Py_ssize_t i, pos, argc, envc; PyObject *(*getitem)(PyObject *, Py_ssize_t); - int lastarg = 0; + Py_ssize_t lastarg = 0; /* execve has three arguments: (path, argv, env), where argv is a list or tuple of strings and env is a dictionary @@ -2581,7 +2817,8 @@ posix_spawnv(PyObject *self, PyObject *args) char *path; PyObject *argv; char **argvlist; - int mode, i, argc; + int mode, i; + Py_ssize_t argc; Py_intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); @@ -2670,10 +2907,11 @@ posix_spawnve(PyObject *self, PyObject *args) char **argvlist; char **envlist; PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; - int mode, i, pos, argc, envc; + int mode, pos, envc; + Py_ssize_t argc, i; Py_intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); - int lastarg = 0; + Py_ssize_t lastarg = 0; /* spawnve has four arguments: (mode, path, argv, env), where argv is a list or tuple of strings and env is a dictionary @@ -4374,7 +4612,7 @@ _PyPopenCreateProcess(char *cmdstring, char modulepath[_MAX_PATH]; struct stat statinfo; GetModuleFileName(NULL, modulepath, sizeof(modulepath)); - for (i = x = 0; modulepath[i]; i++) + for (x = i = 0; modulepath[i]; i++) if (modulepath[i] == SEP) x = i+1; modulepath[x] = '\0'; @@ -4551,7 +4789,7 @@ _PyPopen(char *cmdstring, int mode, int n) switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) { case _O_WRONLY | _O_TEXT: /* Case for writing to child Stdin in text mode. */ - fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); f1 = _fdopen(fd1, "w"); f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose); PyFile_SetBufSize(f, 0); @@ -4562,7 +4800,7 @@ _PyPopen(char *cmdstring, int mode, int n) case _O_RDONLY | _O_TEXT: /* Case for reading from child Stdout in text mode. */ - fd1 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); + fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); f1 = _fdopen(fd1, "r"); f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose); PyFile_SetBufSize(f, 0); @@ -4573,7 +4811,7 @@ _PyPopen(char *cmdstring, int mode, int n) case _O_RDONLY | _O_BINARY: /* Case for readinig from child Stdout in binary mode. */ - fd1 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); + fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); f1 = _fdopen(fd1, "rb"); f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose); PyFile_SetBufSize(f, 0); @@ -4584,7 +4822,7 @@ _PyPopen(char *cmdstring, int mode, int n) case _O_WRONLY | _O_BINARY: /* Case for writing to child Stdin in binary mode. */ - fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); f1 = _fdopen(fd1, "wb"); f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose); PyFile_SetBufSize(f, 0); @@ -4610,9 +4848,9 @@ _PyPopen(char *cmdstring, int mode, int n) m2 = "wb"; } - fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); f1 = _fdopen(fd1, m2); - fd2 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); + fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); f2 = _fdopen(fd2, m1); p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose); PyFile_SetBufSize(p1, 0); @@ -4642,11 +4880,11 @@ _PyPopen(char *cmdstring, int mode, int n) m2 = "wb"; } - fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode); + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); f1 = _fdopen(fd1, m2); - fd2 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode); + fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); f2 = _fdopen(fd2, m1); - fd3 = _open_osfhandle((intptr_t)hChildStderrRdDup, mode); + fd3 = _open_osfhandle((Py_intptr_t)hChildStderrRdDup, mode); f3 = _fdopen(fd3, m1); p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose); p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose); @@ -5250,7 +5488,7 @@ PyDoc_STRVAR(posix_waitpid__doc__, static PyObject * posix_waitpid(PyObject *self, PyObject *args) { - intptr_t pid; + Py_intptr_t pid; int status, options; if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options)) @@ -5339,7 +5577,7 @@ Create a symbolic link pointing to src named dst."); static PyObject * posix_symlink(PyObject *self, PyObject *args) { - return posix_2str(args, "etet:symlink", symlink, NULL, NULL); + return posix_2str(args, "etet:symlink", symlink); } #endif /* HAVE_SYMLINK */ @@ -6280,7 +6518,7 @@ posix_WSTOPSIG(PyObject *self, PyObject *args) #endif /* HAVE_SYS_WAIT_H */ -#if defined(HAVE_FSTATVFS) +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) #ifdef _SCO_DS /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the needed definitions in sys/statvfs.h */ @@ -6347,10 +6585,10 @@ posix_fstatvfs(PyObject *self, PyObject *args) return _pystatvfs_fromstructstatvfs(st); } -#endif /* HAVE_FSTATVFS */ +#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */ -#if defined(HAVE_STATVFS) +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) #include <sys/statvfs.h> PyDoc_STRVAR(posix_statvfs__doc__, @@ -7888,10 +8126,10 @@ static PyMethodDef posix_methods[] = { {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__}, #endif /* WSTOPSIG */ #endif /* HAVE_SYS_WAIT_H */ -#ifdef HAVE_FSTATVFS +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__}, #endif -#ifdef HAVE_STATVFS +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) {"statvfs", posix_statvfs, METH_VARARGS, posix_statvfs__doc__}, #endif #ifdef HAVE_TMPFILE @@ -8264,6 +8502,45 @@ INITFUNC(void) PyModule_AddObject(m, "statvfs_result", (PyObject*) &StatVFSResultType); initialized = 1; + +#ifdef __APPLE__ + /* + * Step 2 of weak-linking support on Mac OS X. + * + * The code below removes functions that are not available on the + * currently active platform. + * + * This block allow one to use a python binary that was build on + * OSX 10.4 on OSX 10.3, without loosing access to new APIs on + * OSX 10.4. + */ +#ifdef HAVE_FSTATVFS + if (fstatvfs == NULL) { + if (PyObject_DelAttrString(m, "fstatvfs") == -1) { + return; + } + } +#endif /* HAVE_FSTATVFS */ + +#ifdef HAVE_STATVFS + if (statvfs == NULL) { + if (PyObject_DelAttrString(m, "statvfs") == -1) { + return; + } + } +#endif /* HAVE_STATVFS */ + +# ifdef HAVE_LCHOWN + if (lchown == NULL) { + if (PyObject_DelAttrString(m, "lchown") == -1) { + return; + } + } +#endif /* HAVE_LCHOWN */ + + +#endif /* __APPLE__ */ + } #ifdef __cplusplus diff --git a/Modules/rotatingtree.h b/Modules/rotatingtree.h index 97cc8e8..3aa0986 100644 --- a/Modules/rotatingtree.h +++ b/Modules/rotatingtree.h @@ -4,7 +4,7 @@ * * It's a dict-like data structure that works best when accesses are not * random, but follow a strong pattern. The one implemented here is for - * accesses patterns where the same small set of keys is looked up over + * access patterns where the same small set of keys is looked up over * and over again, and this set of keys evolves slowly over time. */ diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index c9d403a..4a04af1 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -8,6 +8,13 @@ #include "Python.h" +#ifdef __APPLE__ + /* Perform runtime testing for a broken poll on OSX to make it easier + * to use the same binary on multiple releases of the OS. + */ +#undef HAVE_BROKEN_POLL +#endif + /* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. 64 is too small (too many people have bumped into that limit). Here we boost it. @@ -618,7 +625,38 @@ select_poll(PyObject *self, PyObject *args) return NULL; return (PyObject *)rv; } -#endif /* HAVE_POLL && !HAVE_BROKEN_POLL */ + +#ifdef __APPLE__ +/* + * On some systems poll() sets errno on invalid file descriptors. We test + * for this at runtime because this bug may be fixed or introduced between + * OS releases. + */ +static int select_have_broken_poll(void) +{ + int poll_test; + int filedes[2]; + + struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 }; + + /* Create a file descriptor to make invalid */ + if (pipe(filedes) < 0) { + return 1; + } + poll_struct.fd = filedes[0]; + close(filedes[0]); + close(filedes[1]); + poll_test = poll(&poll_struct, 1, 0); + if (poll_test < 0) { + return 1; + } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) { + return 1; + } + return 0; +} +#endif /* __APPLE__ */ + +#endif /* HAVE_POLL */ PyDoc_STRVAR(select_doc, "select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\ @@ -645,9 +683,9 @@ On Windows, only sockets are supported; on Unix, all file descriptors."); static PyMethodDef select_methods[] = { {"select", select_select, METH_VARARGS, select_doc}, -#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) +#if defined(HAVE_POLL) {"poll", select_poll, METH_VARARGS, poll_doc}, -#endif /* HAVE_POLL && !HAVE_BROKEN_POLL */ +#endif /* HAVE_POLL */ {0, 0}, /* sentinel */ }; @@ -668,29 +706,40 @@ initselect(void) SelectError = PyErr_NewException("select.error", NULL, NULL); Py_INCREF(SelectError); PyModule_AddObject(m, "error", SelectError); -#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) - poll_Type.ob_type = &PyType_Type; - PyModule_AddIntConstant(m, "POLLIN", POLLIN); - PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); - PyModule_AddIntConstant(m, "POLLOUT", POLLOUT); - PyModule_AddIntConstant(m, "POLLERR", POLLERR); - PyModule_AddIntConstant(m, "POLLHUP", POLLHUP); - PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL); +#if defined(HAVE_POLL) + +#ifdef __APPLE__ + if (select_have_broken_poll()) { + if (PyObject_DelAttrString(m, "poll") == -1) { + PyErr_Clear(); + } + } else { +#else + { +#endif + poll_Type.ob_type = &PyType_Type; + PyModule_AddIntConstant(m, "POLLIN", POLLIN); + PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); + PyModule_AddIntConstant(m, "POLLOUT", POLLOUT); + PyModule_AddIntConstant(m, "POLLERR", POLLERR); + PyModule_AddIntConstant(m, "POLLHUP", POLLHUP); + PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL); #ifdef POLLRDNORM - PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM); + PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM); #endif #ifdef POLLRDBAND - PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND); + PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND); #endif #ifdef POLLWRNORM - PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM); + PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM); #endif #ifdef POLLWRBAND - PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND); + PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND); #endif #ifdef POLLMSG - PyModule_AddIntConstant(m, "POLLMSG", POLLMSG); + PyModule_AddIntConstant(m, "POLLMSG", POLLMSG); #endif -#endif /* HAVE_POLL && !HAVE_BROKEN_POLL */ + } +#endif /* HAVE_POLL */ } diff --git a/Modules/sha512module.c b/Modules/sha512module.c index 539204e..c5a85ff 100644 --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -121,12 +121,12 @@ static void SHAcopy(SHAobject *src, SHAobject *dest) /* Various logical functions */ #define ROR64(x, y) \ - ( ((((x) & 0xFFFFFFFFFFFFFFFFULL)>>((unsigned PY_LONG_LONG)(y) & 63)) | \ - ((x)<<((unsigned PY_LONG_LONG)(64-((y) & 63))))) & 0xFFFFFFFFFFFFFFFFULL) + ( ((((x) & Py_ULL(0xFFFFFFFFFFFFFFFF))>>((unsigned PY_LONG_LONG)(y) & 63)) | \ + ((x)<<((unsigned PY_LONG_LONG)(64-((y) & 63))))) & Py_ULL(0xFFFFFFFFFFFFFFFF)) #define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) ROR64((x),(n)) -#define R(x, n) (((x) & 0xFFFFFFFFFFFFFFFFULL) >> ((unsigned PY_LONG_LONG)n)) +#define R(x, n) (((x) & Py_ULL(0xFFFFFFFFFFFFFFFF)) >> ((unsigned PY_LONG_LONG)n)) #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) @@ -156,86 +156,86 @@ sha512_transform(SHAobject *sha_info) d += t0; \ h = t0 + t1; - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98d728ae22ULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x7137449123ef65cdULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcfec4d3b2fULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba58189dbbcULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25bf348b538ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1b605d019ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4af194f9bULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5da6d8118ULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98a3030242ULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b0145706fbeULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be4ee4b28cULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3d5ffb4e2ULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74f27b896fULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe3b1696b1ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a725c71235ULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174cf692694ULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c19ef14ad2ULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786384f25e3ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc68b8cd5b5ULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc77ac9c65ULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f592b0275ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa6ea6e483ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dcbd41fbd4ULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da831153b5ULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152ee66dfabULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d2db43210ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c898fb213fULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7beef0ee4ULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf33da88fc2ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147930aa725ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351e003826fULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x142929670a0e6e70ULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a8546d22ffcULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b21385c26c926ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc5ac42aedULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d139d95b3dfULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a73548baf63deULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb3c77b2a8ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e47edaee6ULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c851482353bULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a14cf10364ULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664bbc423001ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70d0f89791ULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a30654be30ULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819d6ef5218ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd69906245565a910ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e35855771202aULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa07032bbd1b8ULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116b8d2d0c8ULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c085141ab53ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774cdf8eeb99ULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5e19b48a8ULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3c5c95a63ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4ae3418acbULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f7763e373ULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3d6b2b8a3ULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee5defb2fcULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f43172f60ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814a1f0ab72ULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc702081a6439ecULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa23631e28ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506cebde82bde9ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7b2c67915ULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2e372532bULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],64,0xca273eceea26619cULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],65,0xd186b8c721c0c207ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],66,0xeada7dd6cde0eb1eULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],67,0xf57d4f7fee6ed178ULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],68,0x06f067aa72176fbaULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],69,0x0a637dc5a2c898a6ULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],70,0x113f9804bef90daeULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],71,0x1b710b35131c471bULL); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],72,0x28db77f523047d84ULL); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],73,0x32caab7b40c72493ULL); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],74,0x3c9ebe0a15c9bebcULL); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],75,0x431d67c49c100d4cULL); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],76,0x4cc5d4becb3e42b6ULL); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],77,0x597f299cfc657e2aULL); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],78,0x5fcb6fab3ad6faecULL); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],79,0x6c44198c4a475817ULL); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,Py_ULL(0x428a2f98d728ae22)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,Py_ULL(0x7137449123ef65cd)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,Py_ULL(0xb5c0fbcfec4d3b2f)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,Py_ULL(0xe9b5dba58189dbbc)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,Py_ULL(0x3956c25bf348b538)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,Py_ULL(0x59f111f1b605d019)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,Py_ULL(0x923f82a4af194f9b)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,Py_ULL(0xab1c5ed5da6d8118)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,Py_ULL(0xd807aa98a3030242)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,Py_ULL(0x12835b0145706fbe)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,Py_ULL(0x243185be4ee4b28c)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,Py_ULL(0x550c7dc3d5ffb4e2)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,Py_ULL(0x72be5d74f27b896f)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,Py_ULL(0x80deb1fe3b1696b1)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,Py_ULL(0x9bdc06a725c71235)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,Py_ULL(0xc19bf174cf692694)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,Py_ULL(0xe49b69c19ef14ad2)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,Py_ULL(0xefbe4786384f25e3)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,Py_ULL(0x0fc19dc68b8cd5b5)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,Py_ULL(0x240ca1cc77ac9c65)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,Py_ULL(0x2de92c6f592b0275)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,Py_ULL(0x4a7484aa6ea6e483)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,Py_ULL(0x5cb0a9dcbd41fbd4)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,Py_ULL(0x76f988da831153b5)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,Py_ULL(0x983e5152ee66dfab)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,Py_ULL(0xa831c66d2db43210)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,Py_ULL(0xb00327c898fb213f)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,Py_ULL(0xbf597fc7beef0ee4)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,Py_ULL(0xc6e00bf33da88fc2)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,Py_ULL(0xd5a79147930aa725)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,Py_ULL(0x06ca6351e003826f)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,Py_ULL(0x142929670a0e6e70)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,Py_ULL(0x27b70a8546d22ffc)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,Py_ULL(0x2e1b21385c26c926)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,Py_ULL(0x4d2c6dfc5ac42aed)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,Py_ULL(0x53380d139d95b3df)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,Py_ULL(0x650a73548baf63de)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,Py_ULL(0x766a0abb3c77b2a8)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,Py_ULL(0x81c2c92e47edaee6)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,Py_ULL(0x92722c851482353b)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,Py_ULL(0xa2bfe8a14cf10364)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,Py_ULL(0xa81a664bbc423001)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,Py_ULL(0xc24b8b70d0f89791)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,Py_ULL(0xc76c51a30654be30)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,Py_ULL(0xd192e819d6ef5218)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,Py_ULL(0xd69906245565a910)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,Py_ULL(0xf40e35855771202a)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,Py_ULL(0x106aa07032bbd1b8)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,Py_ULL(0x19a4c116b8d2d0c8)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,Py_ULL(0x1e376c085141ab53)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,Py_ULL(0x2748774cdf8eeb99)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,Py_ULL(0x34b0bcb5e19b48a8)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,Py_ULL(0x391c0cb3c5c95a63)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,Py_ULL(0x4ed8aa4ae3418acb)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,Py_ULL(0x5b9cca4f7763e373)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,Py_ULL(0x682e6ff3d6b2b8a3)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,Py_ULL(0x748f82ee5defb2fc)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,Py_ULL(0x78a5636f43172f60)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,Py_ULL(0x84c87814a1f0ab72)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,Py_ULL(0x8cc702081a6439ec)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,Py_ULL(0x90befffa23631e28)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,Py_ULL(0xa4506cebde82bde9)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,Py_ULL(0xbef9a3f7b2c67915)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,Py_ULL(0xc67178f2e372532b)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],64,Py_ULL(0xca273eceea26619c)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],65,Py_ULL(0xd186b8c721c0c207)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],66,Py_ULL(0xeada7dd6cde0eb1e)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],67,Py_ULL(0xf57d4f7fee6ed178)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],68,Py_ULL(0x06f067aa72176fba)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],69,Py_ULL(0x0a637dc5a2c898a6)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],70,Py_ULL(0x113f9804bef90dae)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],71,Py_ULL(0x1b710b35131c471b)); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],72,Py_ULL(0x28db77f523047d84)); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],73,Py_ULL(0x32caab7b40c72493)); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],74,Py_ULL(0x3c9ebe0a15c9bebc)); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],75,Py_ULL(0x431d67c49c100d4c)); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],76,Py_ULL(0x4cc5d4becb3e42b6)); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],77,Py_ULL(0x597f299cfc657e2a)); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],78,Py_ULL(0x5fcb6fab3ad6faec)); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],79,Py_ULL(0x6c44198c4a475817)); #undef RND @@ -254,14 +254,14 @@ static void sha512_init(SHAobject *sha_info) { TestEndianness(sha_info->Endianness) - sha_info->digest[0] = 0x6a09e667f3bcc908ULL; - sha_info->digest[1] = 0xbb67ae8584caa73bULL; - sha_info->digest[2] = 0x3c6ef372fe94f82bULL; - sha_info->digest[3] = 0xa54ff53a5f1d36f1ULL; - sha_info->digest[4] = 0x510e527fade682d1ULL; - sha_info->digest[5] = 0x9b05688c2b3e6c1fULL; - sha_info->digest[6] = 0x1f83d9abfb41bd6bULL; - sha_info->digest[7] = 0x5be0cd19137e2179ULL; + sha_info->digest[0] = Py_ULL(0x6a09e667f3bcc908); + sha_info->digest[1] = Py_ULL(0xbb67ae8584caa73b); + sha_info->digest[2] = Py_ULL(0x3c6ef372fe94f82b); + sha_info->digest[3] = Py_ULL(0xa54ff53a5f1d36f1); + sha_info->digest[4] = Py_ULL(0x510e527fade682d1); + sha_info->digest[5] = Py_ULL(0x9b05688c2b3e6c1f); + sha_info->digest[6] = Py_ULL(0x1f83d9abfb41bd6b); + sha_info->digest[7] = Py_ULL(0x5be0cd19137e2179); sha_info->count_lo = 0L; sha_info->count_hi = 0L; sha_info->local = 0; @@ -272,14 +272,14 @@ static void sha384_init(SHAobject *sha_info) { TestEndianness(sha_info->Endianness) - sha_info->digest[0] = 0xcbbb9d5dc1059ed8ULL; - sha_info->digest[1] = 0x629a292a367cd507ULL; - sha_info->digest[2] = 0x9159015a3070dd17ULL; - sha_info->digest[3] = 0x152fecd8f70e5939ULL; - sha_info->digest[4] = 0x67332667ffc00b31ULL; - sha_info->digest[5] = 0x8eb44a8768581511ULL; - sha_info->digest[6] = 0xdb0c2e0d64f98fa7ULL; - sha_info->digest[7] = 0x47b5481dbefa4fa4ULL; + sha_info->digest[0] = Py_ULL(0xcbbb9d5dc1059ed8); + sha_info->digest[1] = Py_ULL(0x629a292a367cd507); + sha_info->digest[2] = Py_ULL(0x9159015a3070dd17); + sha_info->digest[3] = Py_ULL(0x152fecd8f70e5939); + sha_info->digest[4] = Py_ULL(0x67332667ffc00b31); + sha_info->digest[5] = Py_ULL(0x8eb44a8768581511); + sha_info->digest[6] = Py_ULL(0xdb0c2e0d64f98fa7); + sha_info->digest[7] = Py_ULL(0x47b5481dbefa4fa4); sha_info->count_lo = 0L; sha_info->count_hi = 0L; sha_info->local = 0; diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c9dd4a3..164a5d1 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -61,6 +61,15 @@ Local naming conventions: */ +#ifdef __APPLE__ + /* + * inet_aton is not available on OSX 10.3, yet we want to use a binary + * that was build on 10.4 or later to work on that release, weak linking + * comes to the rescue. + */ +# pragma weak inet_aton +#endif + #include "Python.h" #include "structmember.h" @@ -95,7 +104,10 @@ gettimeout() -- return timeout or None\n\ listen(n) -- start listening for incoming connections\n\ makefile([mode, [bufsize]]) -- return a file object for the socket [*]\n\ recv(buflen[, flags]) -- receive data\n\ -recvfrom(buflen[, flags]) -- receive data and sender's address\n\ +recv_buf(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\ +recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\ +recvfrom_buf(buffer[, nbytes, [, flags])\n\ + -- receive data and sender\'s address (into a buffer)\n\ sendall(data[, flags]) -- send all data\n\ send(data[, flags]) -- send data, may not send all of it\n\ sendto(data[, flags], addr) -- send data to a given address\n\ @@ -196,7 +208,7 @@ shutdown(how) -- shut down traffic in one or both directions\n\ functions are declared correctly if compiling with MIPSPro 7.x in ANSI C mode (default) */ -/* XXX Using _SGIAPI is the wrong thing, +/* XXX Using _SGIAPI is the wrong thing, but I don't know what the right thing is. */ #undef _SGIAPI /* to avoid warning */ #define _SGIAPI 1 @@ -214,8 +226,8 @@ shutdown(how) -- shut down traffic in one or both directions\n\ #include <netdb.h> #endif -/* Irix 6.5 fails to define this variable at all. This is needed - for both GCC and SGI's compiler. I'd say that the SGI headers +/* Irix 6.5 fails to define this variable at all. This is needed + for both GCC and SGI's compiler. I'd say that the SGI headers are just busted. Same thing for Solaris. */ #if (defined(__sgi) || defined(sun)) && !defined(INET_ADDRSTRLEN) #define INET_ADDRSTRLEN 16 @@ -306,6 +318,11 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); older releases don't have */ #undef HAVE_GETADDRINFO #endif + +#ifdef HAVE_INET_ATON +#define USE_INET_ATON_WEAKLINK +#endif + #endif /* I know this is a bad practice, but it is the easiest... */ @@ -1180,10 +1197,10 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, args->ob_type->tp_name); return 0; } - if (!PyArg_ParseTuple(args, "eti:getsockaddrarg", + if (!PyArg_ParseTuple(args, "eti:getsockaddrarg", "idna", &host, &port)) return 0; - result = setipaddr(host, (struct sockaddr *)addr, + result = setipaddr(host, (struct sockaddr *)addr, sizeof(*addr), AF_INET); PyMem_Free(host); if (result < 0) @@ -1203,12 +1220,20 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, int port, flowinfo, scope_id, result; addr = (struct sockaddr_in6*)&(s->sock_addr).in6; flowinfo = scope_id = 0; - if (!PyArg_ParseTuple(args, "eti|ii", + if (!PyTuple_Check(args)) { + PyErr_Format( + PyExc_TypeError, + "getsockaddrarg: " + "AF_INET6 address must be tuple, not %.500s", + args->ob_type->tp_name); + return 0; + } + if (!PyArg_ParseTuple(args, "eti|ii", "idna", &host, &port, &flowinfo, &scope_id)) { return 0; } - result = setipaddr(host, (struct sockaddr *)addr, + result = setipaddr(host, (struct sockaddr *)addr, sizeof(*addr), AF_INET6); PyMem_Free(host); if (result < 0) @@ -1305,6 +1330,14 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, char *haddr = NULL; unsigned int halen = 0; + if (!PyTuple_Check(args)) { + PyErr_Format( + PyExc_TypeError, + "getsockaddrarg: " + "AF_PACKET address must be tuple, not %.500s", + args->ob_type->tp_name); + return 0; + } if (!PyArg_ParseTuple(args, "si|iis#", &interfaceName, &protoNumber, &pkttype, &hatype, &haddr, &halen)) @@ -1809,7 +1842,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, int res_size = sizeof res; /* It must be in the exception set */ assert(FD_ISSET(s->sock_fd, &fds_exc)); - if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, + if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, (char *)&res, &res_size)) /* getsockopt also clears WSAGetLastError, so reset it back. */ @@ -2105,95 +2138,126 @@ The mode and buffersize arguments are as for the built-in open() function."); #endif /* NO_DUP */ - -/* s.recv(nbytes [,flags]) method */ - -static PyObject * -sock_recv(PySocketSockObject *s, PyObject *args) +/* + * This is the guts of the recv() and recv_buf() methods, which reads into a + * char buffer. If you have any inc/def ref to do to the objects that contain + * the buffer, do it in the caller. This function returns the number of bytes + * succesfully read. If there was an error, it returns -1. Note that it is + * also possible that we return a number of bytes smaller than the request + * bytes. + */ +static int +sock_recv_guts(PySocketSockObject *s, char* cbuf, int len, int flags) { - int len, n = 0, flags = 0, timeout; - PyObject *buf; + int timeout, outlen = 0; #ifdef __VMS - int read_length; + int remaining, nread; char *read_buf; #endif - if (!PyArg_ParseTuple(args, "i|i:recv", &len, &flags)) - return NULL; - - if (len < 0) { - PyErr_SetString(PyExc_ValueError, - "negative buffersize in recv"); - return NULL; + if (!IS_SELECTABLE(s)) { + select_error(); + return -1; } - buf = PyString_FromStringAndSize((char *) 0, len); - if (buf == NULL) - return NULL; - - if (!IS_SELECTABLE(s)) - return select_error(); - #ifndef __VMS Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 0); if (!timeout) - n = recv(s->sock_fd, PyString_AS_STRING(buf), len, flags); + outlen = recv(s->sock_fd, cbuf, len, flags); Py_END_ALLOW_THREADS if (timeout) { - Py_DECREF(buf); PyErr_SetString(socket_timeout, "timed out"); - return NULL; + return -1; } - if (n < 0) { - Py_DECREF(buf); - return s->errorhandler(); + if (outlen < 0) { + /* Note: the call to errorhandler() ALWAYS indirectly returned + NULL, so ignore its return value */ + s->errorhandler(); + return -1; } - if (n != len) - _PyString_Resize(&buf, n); #else - read_buf = PyString_AsString(buf); - read_length = len; - while (read_length != 0) { + read_buf = cbuf; + remaining = len; + while (remaining != 0) { unsigned int segment; - segment = read_length /SEGMENT_SIZE; + segment = remaining /SEGMENT_SIZE; if (segment != 0) { segment = SEGMENT_SIZE; } else { - segment = read_length; + segment = remaining; } Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 0); if (!timeout) - n = recv(s->sock_fd, read_buf, segment, flags); + nread = recv(s->sock_fd, read_buf, segment, flags); Py_END_ALLOW_THREADS if (timeout) { - Py_DECREF(buf); PyErr_SetString(socket_timeout, "timed out"); - return NULL; + return -1; } - if (n < 0) { - Py_DECREF(buf); - return s->errorhandler(); + if (nread < 0) { + s->errorhandler(); + return -1; } - if (n != read_length) { - read_buf += n; + if (nread != remaining) { + read_buf += nread; break; } - read_length -= segment; + remaining -= segment; read_buf += segment; } - if (_PyString_Resize(&buf, (read_buf - PyString_AsString(buf))) < 0) - { - return NULL; - } + outlen = read_buf - cbuf; #endif /* !__VMS */ + + return outlen; +} + + +/* s.recv(nbytes [,flags]) method */ + +static PyObject * +sock_recv(PySocketSockObject *s, PyObject *args) +{ + int recvlen, flags = 0, outlen; + PyObject *buf; + + if (!PyArg_ParseTuple(args, "i|i:recv", &recvlen, &flags)) + return NULL; + + if (recvlen < 0) { + PyErr_SetString(PyExc_ValueError, + "negative buffersize in recv"); + return NULL; + } + + /* Allocate a new string. */ + buf = PyString_FromStringAndSize((char *) 0, recvlen); + if (buf == NULL) + return NULL; + + /* Call the guts */ + outlen = sock_recv_guts(s, PyString_AsString(buf), recvlen, flags); + if (outlen < 0) { + /* An error occured, release the string and return an + error. */ + Py_DECREF(buf); + return NULL; + } + if (outlen != recvlen) { + /* We did not read as many bytes as we anticipated, resize the + string if possible and be succesful. */ + if (_PyString_Resize(&buf, outlen) < 0) + /* Oopsy, not so succesful after all. */ + return NULL; + } + return buf; } @@ -2206,29 +2270,90 @@ at least one byte is available or until the remote end is closed. When\n\ the remote end is closed and all data is read, return the empty string."); -/* s.recvfrom(nbytes [,flags]) method */ +/* s.recv_buf(buffer, [nbytes [,flags]]) method */ -static PyObject * -sock_recvfrom(PySocketSockObject *s, PyObject *args) +static PyObject* +sock_recv_buf(PySocketSockObject *s, PyObject *args, PyObject *kwds) { - sock_addr_t addrbuf; - PyObject *buf = NULL; - PyObject *addr = NULL; - PyObject *ret = NULL; - int len, n = 0, flags = 0, timeout; - socklen_t addrlen; + static char *kwlist[] = {"buffer", "nbytes", "flags", 0}; + + int recvlen = 0, flags = 0, readlen; + char *buf; + int buflen; - if (!PyArg_ParseTuple(args, "i|i:recvfrom", &len, &flags)) + /* Get the buffer's memory */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|ii:recv", kwlist, + &buf, &buflen, &recvlen, &flags)) return NULL; + assert(buf != 0 && buflen > 0); - if (!getsockaddrlen(s, &addrlen)) + if (recvlen < 0) { + PyErr_SetString(PyExc_ValueError, + "negative buffersize in recv"); return NULL; - buf = PyString_FromStringAndSize((char *) 0, len); - if (buf == NULL) + } + if (recvlen == 0) { + /* If nbytes was not specified, use the buffer's length */ + recvlen = buflen; + } + + /* Check if the buffer is large enough */ + if (buflen < recvlen) { + PyErr_SetString(PyExc_ValueError, + "buffer too small for requested bytes"); return NULL; + } - if (!IS_SELECTABLE(s)) - return select_error(); + /* Call the guts */ + readlen = sock_recv_guts(s, buf, recvlen, flags); + if (readlen < 0) { + /* Return an error. */ + return NULL; + } + + /* Return the number of bytes read. Note that we do not do anything + special here in the case that readlen < recvlen. */ + return PyInt_FromLong(readlen); +} + +PyDoc_STRVAR(recv_buf_doc, +"recv_buf(buffer, [nbytes[, flags]]) -> nbytes_read\n\ +\n\ +A version of recv() that stores its data into a buffer rather than creating \n\ +a new string. Receive up to buffersize bytes from the socket. If buffersize \n\ +is not specified (or 0), receive up to the size available in the given buffer.\n\ +\n\ +See recv() for documentation about the flags."); + + +/* + * This is the guts of the recv() and recv_buf() methods, which reads into a + * char buffer. If you have any inc/def ref to do to the objects that contain + * the buffer, do it in the caller. This function returns the number of bytes + * succesfully read. If there was an error, it returns -1. Note that it is + * also possible that we return a number of bytes smaller than the request + * bytes. + * + * 'addr' is a return value for the address object. Note that you must decref + * it yourself. + */ +static int +sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, int len, int flags, + PyObject** addr) +{ + sock_addr_t addrbuf; + int n = 0, timeout; + socklen_t addrlen; + + *addr = NULL; + + if (!getsockaddrlen(s, &addrlen)) + return -1; + + if (!IS_SELECTABLE(s)) { + select_error(); + return -1; + } Py_BEGIN_ALLOW_THREADS memset(&addrbuf, 0, addrlen); @@ -2236,41 +2361,71 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args) if (!timeout) { #ifndef MS_WINDOWS #if defined(PYOS_OS2) && !defined(PYCC_GCC) - n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags, + n = recvfrom(s->sock_fd, cbuf, len, flags, (struct sockaddr *) &addrbuf, &addrlen); #else - n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags, + n = recvfrom(s->sock_fd, cbuf, len, flags, (void *) &addrbuf, &addrlen); #endif #else - n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags, + n = recvfrom(s->sock_fd, cbuf, len, flags, (struct sockaddr *) &addrbuf, &addrlen); #endif } Py_END_ALLOW_THREADS if (timeout) { - Py_DECREF(buf); PyErr_SetString(socket_timeout, "timed out"); - return NULL; + return -1; } if (n < 0) { - Py_DECREF(buf); - return s->errorhandler(); + s->errorhandler(); + return -1; } - if (n != len && _PyString_Resize(&buf, n) < 0) + if (!(*addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf, + addrlen, s->sock_proto))) + return -1; + + return n; +} + +/* s.recvfrom(nbytes [,flags]) method */ + +static PyObject * +sock_recvfrom(PySocketSockObject *s, PyObject *args) +{ + PyObject *buf = NULL; + PyObject *addr = NULL; + PyObject *ret = NULL; + int recvlen, outlen, flags = 0; + + if (!PyArg_ParseTuple(args, "i|i:recvfrom", &recvlen, &flags)) return NULL; - if (!(addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf, - addrlen, s->sock_proto))) + buf = PyString_FromStringAndSize((char *) 0, recvlen); + if (buf == NULL) + return NULL; + + outlen = sock_recvfrom_guts(s, PyString_AS_STRING(buf), + recvlen, flags, &addr); + if (outlen < 0) { goto finally; + } + + if (outlen != recvlen) { + /* We did not read as many bytes as we anticipated, resize the + string if possible and be succesful. */ + if (_PyString_Resize(&buf, outlen) < 0) + /* Oopsy, not so succesful after all. */ + goto finally; + } ret = PyTuple_Pack(2, buf, addr); finally: - Py_XDECREF(addr); Py_XDECREF(buf); + Py_XDECREF(addr); return ret; } @@ -2279,6 +2434,57 @@ PyDoc_STRVAR(recvfrom_doc, \n\ Like recv(buffersize, flags) but also return the sender's address info."); + +/* s.recvfrom_buf(buffer[, nbytes [,flags]]) method */ + +static PyObject * +sock_recvfrom_buf(PySocketSockObject *s, PyObject *args, PyObject* kwds) +{ + static char *kwlist[] = {"buffer", "nbytes", "flags", 0}; + + int recvlen = 0, flags = 0, readlen; + char *buf; + int buflen; + + PyObject *addr = NULL; + PyObject *ret = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|ii:recvfrom", kwlist, + &buf, &buflen, &recvlen, &flags)) + return NULL; + assert(buf != 0 && buflen > 0); + + if (recvlen < 0) { + PyErr_SetString(PyExc_ValueError, + "negative buffersize in recv"); + return NULL; + } + if (recvlen == 0) { + /* If nbytes was not specified, use the buffer's length */ + recvlen = buflen; + } + + readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr); + if (readlen < 0) { + /* Return an error */ + goto finally; + } + + /* Return the number of bytes read and the address. Note that we do + not do anything special here in the case that readlen < recvlen. */ + ret = PyTuple_Pack(2, PyInt_FromLong(readlen), addr); + +finally: + Py_XDECREF(addr); + return ret; +} + +PyDoc_STRVAR(recvfrom_buf_doc, +"recvfrom_buf(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\ +\n\ +Like recv_buf(buffer[, nbytes[, flags]]) but also return the sender's address info."); + + /* s.send(data [,flags]) method */ static PyObject * @@ -2473,59 +2679,63 @@ of the socket (flag == SHUT_WR), or both ends (flag == SHUT_RDWR)."); /* List of methods for socket objects */ static PyMethodDef sock_methods[] = { - {"accept", (PyCFunction)sock_accept, METH_NOARGS, - accept_doc}, - {"bind", (PyCFunction)sock_bind, METH_O, - bind_doc}, - {"close", (PyCFunction)sock_close, METH_NOARGS, - close_doc}, - {"connect", (PyCFunction)sock_connect, METH_O, - connect_doc}, - {"connect_ex", (PyCFunction)sock_connect_ex, METH_O, - connect_ex_doc}, + {"accept", (PyCFunction)sock_accept, METH_NOARGS, + accept_doc}, + {"bind", (PyCFunction)sock_bind, METH_O, + bind_doc}, + {"close", (PyCFunction)sock_close, METH_NOARGS, + close_doc}, + {"connect", (PyCFunction)sock_connect, METH_O, + connect_doc}, + {"connect_ex", (PyCFunction)sock_connect_ex, METH_O, + connect_ex_doc}, #ifndef NO_DUP - {"dup", (PyCFunction)sock_dup, METH_NOARGS, - dup_doc}, + {"dup", (PyCFunction)sock_dup, METH_NOARGS, + dup_doc}, #endif - {"fileno", (PyCFunction)sock_fileno, METH_NOARGS, - fileno_doc}, + {"fileno", (PyCFunction)sock_fileno, METH_NOARGS, + fileno_doc}, #ifdef HAVE_GETPEERNAME - {"getpeername", (PyCFunction)sock_getpeername, - METH_NOARGS, getpeername_doc}, -#endif - {"getsockname", (PyCFunction)sock_getsockname, - METH_NOARGS, getsockname_doc}, - {"getsockopt", (PyCFunction)sock_getsockopt, METH_VARARGS, - getsockopt_doc}, - {"listen", (PyCFunction)sock_listen, METH_O, - listen_doc}, + {"getpeername", (PyCFunction)sock_getpeername, + METH_NOARGS, getpeername_doc}, +#endif + {"getsockname", (PyCFunction)sock_getsockname, + METH_NOARGS, getsockname_doc}, + {"getsockopt", (PyCFunction)sock_getsockopt, METH_VARARGS, + getsockopt_doc}, + {"listen", (PyCFunction)sock_listen, METH_O, + listen_doc}, #ifndef NO_DUP - {"makefile", (PyCFunction)sock_makefile, METH_VARARGS, - makefile_doc}, -#endif - {"recv", (PyCFunction)sock_recv, METH_VARARGS, - recv_doc}, - {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS, - recvfrom_doc}, - {"send", (PyCFunction)sock_send, METH_VARARGS, - send_doc}, - {"sendall", (PyCFunction)sock_sendall, METH_VARARGS, - sendall_doc}, - {"sendto", (PyCFunction)sock_sendto, METH_VARARGS, - sendto_doc}, - {"setblocking", (PyCFunction)sock_setblocking, METH_O, - setblocking_doc}, - {"settimeout", (PyCFunction)sock_settimeout, METH_O, - settimeout_doc}, - {"gettimeout", (PyCFunction)sock_gettimeout, METH_NOARGS, - gettimeout_doc}, - {"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS, - setsockopt_doc}, - {"shutdown", (PyCFunction)sock_shutdown, METH_O, - shutdown_doc}, + {"makefile", (PyCFunction)sock_makefile, METH_VARARGS, + makefile_doc}, +#endif + {"recv", (PyCFunction)sock_recv, METH_VARARGS, + recv_doc}, + {"recv_buf", (PyCFunction)sock_recv_buf, METH_VARARGS | METH_KEYWORDS, + recv_buf_doc}, + {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS, + recvfrom_doc}, + {"recvfrom_buf", (PyCFunction)sock_recvfrom_buf, METH_VARARGS | METH_KEYWORDS, + recvfrom_buf_doc}, + {"send", (PyCFunction)sock_send, METH_VARARGS, + send_doc}, + {"sendall", (PyCFunction)sock_sendall, METH_VARARGS, + sendall_doc}, + {"sendto", (PyCFunction)sock_sendto, METH_VARARGS, + sendto_doc}, + {"setblocking", (PyCFunction)sock_setblocking, METH_O, + setblocking_doc}, + {"settimeout", (PyCFunction)sock_settimeout, METH_O, + settimeout_doc}, + {"gettimeout", (PyCFunction)sock_gettimeout, METH_NOARGS, + gettimeout_doc}, + {"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS, + setsockopt_doc}, + {"shutdown", (PyCFunction)sock_shutdown, METH_O, + shutdown_doc}, #ifdef RISCOS - {"sleeptaskw", (PyCFunction)sock_sleeptaskw, METH_O, - sleeptaskw_doc}, + {"sleeptaskw", (PyCFunction)sock_sleeptaskw, METH_O, + sleeptaskw_doc}, #endif {NULL, NULL} /* sentinel */ }; @@ -3333,7 +3543,9 @@ socket_inet_aton(PyObject *self, PyObject *args) #endif #ifdef HAVE_INET_ATON struct in_addr buf; -#else +#endif + +#if !defined(HAVE_INET_ATON) || defined(USE_INET_ATON_WEAKLINK) /* Have to use inet_addr() instead */ unsigned long packed_addr; #endif @@ -3344,6 +3556,10 @@ socket_inet_aton(PyObject *self, PyObject *args) #ifdef HAVE_INET_ATON + +#ifdef USE_INET_ATON_WEAKLINK + if (inet_aton != NULL) { +#endif if (inet_aton(ip_addr, &buf)) return PyString_FromStringAndSize((char *)(&buf), sizeof(buf)); @@ -3352,13 +3568,20 @@ socket_inet_aton(PyObject *self, PyObject *args) "illegal IP address string passed to inet_aton"); return NULL; -#else /* ! HAVE_INET_ATON */ +#ifdef USE_INET_ATON_WEAKLINK + } else { +#endif + +#endif + +#if !defined(HAVE_INET_ATON) || defined(USE_INET_ATON_WEAKLINK) + /* special-case this address as inet_addr might return INADDR_NONE * for this */ if (strcmp(ip_addr, "255.255.255.255") == 0) { packed_addr = 0xFFFFFFFF; } else { - + packed_addr = inet_addr(ip_addr); if (packed_addr == INADDR_NONE) { /* invalid address */ @@ -3369,6 +3592,11 @@ socket_inet_aton(PyObject *self, PyObject *args) } return PyString_FromStringAndSize((char *) &packed_addr, sizeof(packed_addr)); + +#ifdef USE_INET_ATON_WEAKLINK + } +#endif + #endif } @@ -3428,7 +3656,7 @@ socket_inet_pton(PyObject *self, PyObject *args) "can't use AF_INET6, IPv6 is disabled"); return NULL; } -#endif +#endif retval = inet_pton(af, ip, packed); if (retval < 0) { @@ -3451,7 +3679,7 @@ socket_inet_pton(PyObject *self, PyObject *args) return NULL; } } - + PyDoc_STRVAR(inet_ntop_doc, "inet_ntop(af, packed_ip) -> string formatted IP address\n\ \n\ @@ -3469,7 +3697,7 @@ socket_inet_ntop(PyObject *self, PyObject *args) #else char ip[INET_ADDRSTRLEN + 1]; #endif - + /* Guarantee NUL-termination for PyString_FromString() below */ memset((void *) &ip[0], '\0', sizeof(ip)); @@ -3547,7 +3775,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args) } else if (PyString_Check(hobj)) { hptr = PyString_AsString(hobj); } else { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_TypeError, "getaddrinfo() argument 1 must be string or None"); return NULL; } diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c index 83313df..9ac9881 100644 --- a/Modules/threadmodule.c +++ b/Modules/threadmodule.c @@ -98,13 +98,6 @@ PyDoc_STRVAR(locked_doc, \n\ Return whether the lock is in the locked state."); -static PyObject * -lock_context(lockobject *self) -{ - Py_INCREF(self); - return (PyObject *)self; -} - static PyMethodDef lock_methods[] = { {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, METH_VARARGS, acquire_doc}, @@ -118,8 +111,6 @@ static PyMethodDef lock_methods[] = { METH_NOARGS, locked_doc}, {"locked", (PyCFunction)lock_locked_lock, METH_NOARGS, locked_doc}, - {"__context__", (PyCFunction)lock_context, - METH_NOARGS, PyDoc_STR("__context__() -> self.")}, {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, METH_VARARGS, acquire_doc}, {"__exit__", (PyCFunction)lock_PyThread_release_lock, diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 08d28a1..e03b7e1 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -5,6 +5,18 @@ #include "structseq.h" #include "timefuncs.h" +#ifdef __APPLE__ +#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) + /* + * floattime falls back to ftime when getttimeofday fails because the latter + * might fail on some platforms. This fallback is unwanted on MacOSX because + * that makes it impossible to use a binary build on OSX 10.4 on earlier + * releases of the OS. Therefore claim we don't support ftime. + */ +# undef HAVE_FTIME +#endif +#endif + #include <ctype.h> #include <sys/types.h> @@ -51,11 +63,10 @@ static long main_thread; #endif /* MS_WINDOWS */ #endif /* !__WATCOMC__ || __QNX__ */ -#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__) -/* Win32 has better clock replacement - XXX Win64 does not yet, but might when the platform matures. */ -#undef HAVE_CLOCK /* We have our own version down below */ -#endif /* MS_WINDOWS && !MS_WIN64 */ +#if defined(MS_WINDOWS) && !defined(__BORLANDC__) +/* Win32 has better clock replacement; we have our own version below. */ +#undef HAVE_CLOCK +#endif /* MS_WINDOWS && !defined(__BORLANDC__) */ #if defined(PYOS_OS2) #define INCL_DOS @@ -150,7 +161,7 @@ time_clock(PyObject *self, PyObject *args) } #endif /* HAVE_CLOCK */ -#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__) +#if defined(MS_WINDOWS) && !defined(__BORLANDC__) /* Due to Mark Hammond and Tim Peters */ static PyObject * time_clock(PyObject *self, PyObject *args) @@ -179,7 +190,7 @@ time_clock(PyObject *self, PyObject *args) } #define HAVE_CLOCK /* So it gets included in the methods */ -#endif /* MS_WINDOWS && !MS_WIN64 */ +#endif /* MS_WINDOWS && !defined(__BORLANDC__) */ #ifdef HAVE_CLOCK PyDoc_STRVAR(clock_doc, @@ -701,7 +712,7 @@ void inittimezone(PyObject *m) { #ifdef __CYGWIN__ tzset(); PyModule_AddIntConstant(m, "timezone", _timezone); - PyModule_AddIntConstant(m, "altzone", _timezone); + PyModule_AddIntConstant(m, "altzone", _timezone-3600); PyModule_AddIntConstant(m, "daylight", _daylight); PyModule_AddObject(m, "tzname", Py_BuildValue("(zz)", _tzname[0], _tzname[1])); @@ -809,7 +820,7 @@ inittime(void) SetConsoleCtrlHandler( PyCtrlHandler, TRUE); #endif /* MS_WINDOWS */ if (!initialized) { - PyStructSequence_InitType(&StructTimeType, + PyStructSequence_InitType(&StructTimeType, &struct_time_type_desc); } Py_INCREF(&StructTimeType); @@ -842,6 +853,7 @@ floattime(void) return (double)t.tv_sec + t.tv_usec*0.000001; #endif /* !GETTIMEOFDAY_NO_TZ */ } + #endif /* !HAVE_GETTIMEOFDAY */ { #if defined(HAVE_FTIME) diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 297611c..0660353 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -209,7 +209,7 @@ unicodedata_numeric(PyObject *self, PyObject *args) if (old->category_changed == 0) { /* unassigned */ have_old = 1; - rc = -1; + rc = -1.0; } else if (old->decimal_changed != 0xFF) { have_old = 1; @@ -219,7 +219,7 @@ unicodedata_numeric(PyObject *self, PyObject *args) if (!have_old) rc = Py_UNICODE_TONUMERIC(*PyUnicode_AS_UNICODE(v)); - if (rc < 0) { + if (rc == -1.0) { if (defobj == NULL) { PyErr_SetString(PyExc_ValueError, "not a numeric character"); return NULL; diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 35b8c32..06b0690 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -653,6 +653,108 @@ PyZlib_flush(compobject *self, PyObject *args) return RetVal; } +PyDoc_STRVAR(comp_copy__doc__, +"copy() -- Return a copy of the compression object."); + +static PyObject * +PyZlib_copy(compobject *self) +{ + compobject *retval = NULL; + int err; + + retval = newcompobject(&Comptype); + if (!retval) return NULL; + + /* Copy the zstream state + * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe + */ + ENTER_ZLIB + err = deflateCopy(&retval->zst, &self->zst); + switch(err) { + case(Z_OK): + break; + case(Z_STREAM_ERROR): + PyErr_SetString(PyExc_ValueError, "Inconsistent stream state"); + goto error; + case(Z_MEM_ERROR): + PyErr_SetString(PyExc_MemoryError, + "Can't allocate memory for compression object"); + goto error; + default: + zlib_error(self->zst, err, "while copying compression object"); + goto error; + } + + Py_INCREF(self->unused_data); + Py_INCREF(self->unconsumed_tail); + Py_XDECREF(retval->unused_data); + Py_XDECREF(retval->unconsumed_tail); + retval->unused_data = self->unused_data; + retval->unconsumed_tail = self->unconsumed_tail; + + /* Mark it as being initialized */ + retval->is_initialised = 1; + + LEAVE_ZLIB + return (PyObject *)retval; + +error: + LEAVE_ZLIB + Py_XDECREF(retval); + return NULL; +} + +PyDoc_STRVAR(decomp_copy__doc__, +"copy() -- Return a copy of the decompression object."); + +static PyObject * +PyZlib_uncopy(compobject *self) +{ + compobject *retval = NULL; + int err; + + retval = newcompobject(&Decomptype); + if (!retval) return NULL; + + /* Copy the zstream state + * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe + */ + ENTER_ZLIB + err = inflateCopy(&retval->zst, &self->zst); + switch(err) { + case(Z_OK): + break; + case(Z_STREAM_ERROR): + PyErr_SetString(PyExc_ValueError, "Inconsistent stream state"); + goto error; + case(Z_MEM_ERROR): + PyErr_SetString(PyExc_MemoryError, + "Can't allocate memory for decompression object"); + goto error; + default: + zlib_error(self->zst, err, "while copying decompression object"); + goto error; + } + + Py_INCREF(self->unused_data); + Py_INCREF(self->unconsumed_tail); + Py_XDECREF(retval->unused_data); + Py_XDECREF(retval->unconsumed_tail); + retval->unused_data = self->unused_data; + retval->unconsumed_tail = self->unconsumed_tail; + + /* Mark it as being initialized */ + retval->is_initialised = 1; + + LEAVE_ZLIB + return (PyObject *)retval; + +error: + LEAVE_ZLIB + Py_XDECREF(retval); + return NULL; +} + PyDoc_STRVAR(decomp_flush__doc__, "flush( [length] ) -- Return a string containing any remaining\n" "decompressed data. length, if given, is the initial size of the\n" @@ -725,6 +827,8 @@ static PyMethodDef comp_methods[] = comp_compress__doc__}, {"flush", (binaryfunc)PyZlib_flush, METH_VARARGS, comp_flush__doc__}, + {"copy", (PyCFunction)PyZlib_copy, METH_NOARGS, + comp_copy__doc__}, {NULL, NULL} }; @@ -734,6 +838,8 @@ static PyMethodDef Decomp_methods[] = decomp_decompress__doc__}, {"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS, decomp_flush__doc__}, + {"copy", (PyCFunction)PyZlib_uncopy, METH_NOARGS, + decomp_copy__doc__}, {NULL, NULL} }; |