diff -r 540a9c69c2ea -r 6a9fc0065458 Include/object.h --- a/Include/object.h Fri Sep 13 19:53:08 2013 +0200 +++ b/Include/object.h Sun Oct 06 16:48:10 2013 +0200 @@ -564,15 +564,46 @@ #ifndef Py_LIMITED_API PyAPI_FUNC(Py_hash_t) _Py_HashDouble(double); PyAPI_FUNC(Py_hash_t) _Py_HashPointer(void*); -PyAPI_FUNC(Py_hash_t) _Py_HashBytes(unsigned char*, Py_ssize_t); +/* PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t); */ #endif -typedef struct { - Py_hash_t prefix; - Py_hash_t suffix; +typedef union { + unsigned char uc16[16]; + struct { + Py_hash_t prefix; + Py_hash_t suffix; + } ht; +#ifdef PY_UINT64_T + struct { + PY_UINT64_T k0; + PY_UINT64_T k1; + } ui64; +#endif } _Py_HashSecret_t; PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret; +#define PY_HASH_SIPHASH24 0x53495024 +#define PY_HASH_FNV 0x464E56 + +#ifndef PY_HASH_ALGORITHM +#if defined(PY_UINT64_T) && defined(PY_UINT32_T) +#define PY_HASH_ALGORITHM PY_HASH_SIPHASH24 +#else +#define PY_HASH_ALGORITHM PY_HASH_FNV +#endif /* uint64_t && uint32_t */ +#endif /* PY_HASH_ALGORITHM */ + +typedef Py_hash_t (*PyHash_Func_t)(const void *, Py_ssize_t); + +typedef struct { + PyHash_Func_t hash; + char *name; + int hash_bits; + int seed_bits; +} PyHash_FuncDef; + +PyAPI_DATA(PyHash_FuncDef) PyHash_Func; + #ifdef Py_DEBUG PyAPI_DATA(int) _Py_HashSecret_Initialized; #endif diff -r 540a9c69c2ea -r 6a9fc0065458 Lib/test/test_sys.py --- a/Lib/test/test_sys.py Fri Sep 13 19:53:08 2013 +0200 +++ b/Lib/test/test_sys.py Sun Oct 06 16:48:10 2013 +0200 @@ -430,7 +430,7 @@ self.assertEqual(type(sys.int_info.sizeof_digit), int) self.assertIsInstance(sys.hexversion, int) - self.assertEqual(len(sys.hash_info), 5) + self.assertEqual(len(sys.hash_info), 8) self.assertLess(sys.hash_info.modulus, 2**sys.hash_info.width) # sys.hash_info.modulus should be a prime; we do a quick # probable primality test (doesn't exclude the possibility of @@ -445,6 +445,9 @@ self.assertIsInstance(sys.hash_info.inf, int) self.assertIsInstance(sys.hash_info.nan, int) self.assertIsInstance(sys.hash_info.imag, int) + self.assertIn(sys.hash_info.algorithm, {"fnv", "siphash24"}) + self.assertIn(sys.hash_info.hash_bits, {32, 64}) + self.assertIn(sys.hash_info.seed_bits, {32, 64, 128}) self.assertIsInstance(sys.maxsize, int) self.assertIsInstance(sys.maxunicode, int) diff -r 540a9c69c2ea -r 6a9fc0065458 Makefile.pre.in --- a/Makefile.pre.in Fri Sep 13 19:53:08 2013 +0200 +++ b/Makefile.pre.in Sun Oct 06 16:48:10 2013 +0200 @@ -408,6 +408,7 @@ Objects/floatobject.o \ Objects/frameobject.o \ Objects/funcobject.o \ + Objects/hash.o \ Objects/iterobject.o \ Objects/listobject.o \ Objects/longobject.o \ diff -r 540a9c69c2ea -r 6a9fc0065458 Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Modules/_datetimemodule.c Sun Oct 06 16:48:10 2013 +0200 @@ -2767,7 +2767,7 @@ static Py_hash_t generic_hash(unsigned char *data, int len) { - return _Py_HashBytes(data, len); + return PyHash_Func.hash(data, len); } diff -r 540a9c69c2ea -r 6a9fc0065458 Modules/pyexpat.c --- a/Modules/pyexpat.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Modules/pyexpat.c Sun Oct 06 16:48:10 2013 +0200 @@ -1218,7 +1218,7 @@ * has a backport of this feature where we also define XML_HAS_SET_HASH_SALT * to indicate that we can still use it. */ XML_SetHashSalt(self->itself, - (unsigned long)_Py_HashSecret.prefix); + (unsigned long)_Py_HashSecret.ht.prefix); #endif XML_SetUserData(self->itself, (void *)self); XML_SetUnknownEncodingHandler(self->itself, diff -r 540a9c69c2ea -r 6a9fc0065458 Objects/bytesobject.c --- a/Objects/bytesobject.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Objects/bytesobject.c Sun Oct 06 16:48:10 2013 +0200 @@ -878,7 +878,7 @@ { if (a->ob_shash == -1) { /* Can't fail */ - a->ob_shash = _Py_HashBytes((unsigned char *) a->ob_sval, Py_SIZE(a)); + a->ob_shash = PyHash_Func.hash(a->ob_sval, Py_SIZE(a)); } return a->ob_shash; } diff -r 540a9c69c2ea -r 6a9fc0065458 Objects/hash.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Objects/hash.c Sun Oct 06 16:48:10 2013 +0200 @@ -0,0 +1,210 @@ +/* hash functions implementation + * + * Invariants: + * hashfunc(src, 0) == 0 + * hashfunc(src, len) != -1 + */ + +#include "Python.h" + +#ifdef __cplusplus +extern "C" { +#endif + +_Py_HashSecret_t _Py_HashSecret; + + +#if PY_HASH_ALGORITHM == PY_HASH_FNV +/* Modified Fowler-Noll-Vo (FNV) hash function + */ +static Py_hash_t +fnv(const void *src, Py_ssize_t len) +{ + const unsigned char *p = src; + Py_uhash_t x; + Py_ssize_t i, n; + + /* + We make the hash of the empty string be 0, rather than using + (prefix ^ suffix), since this slightly obfuscates the hash secret + */ + if (len == 0) { + return 0; + } +#ifdef Py_DEBUG + assert(_Py_HashSecret_Initialized); +#endif + n = len / sizeof(Py_uhash_t); /* number of blocks */ + i = n * sizeof(Py_uhash_t); + x = (Py_uhash_t) _Py_HashSecret.ht.prefix; + x ^= (Py_uhash_t) *p << 7; + + /* common aligned case */ + if (_Py_IS_ALIGNED(p, SIZEOF_SIZE_T)) { + while (n--) { + Py_uhash_t value = (Py_uhash_t) *p; + x = (_PyHASH_MULTIPLIER * x) ^ value; + p += sizeof(Py_uhash_t); + } + } + /* uncommon non-aligned case with memcpy() */ + else { + union { + Py_uhash_t value; + unsigned char bytes[sizeof(Py_uhash_t)]; + } block; + while (n--) { + memcpy(block.bytes, p, sizeof(Py_uhash_t)); + x = (_PyHASH_MULTIPLIER * x) ^ block.value; + p += sizeof(Py_uhash_t); + } + } + /* add remainder */ + for (; i < len; i++) + x = (_PyHASH_MULTIPLIER * x) ^ (Py_uhash_t) *p++; + x ^= (Py_uhash_t) len; + x ^= (Py_uhash_t) _Py_HashSecret.ht.suffix; + if (x == -1) { + x = -2; + } + return x; +} + +PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * sizeof(Py_hash_t), + 16 * sizeof(Py_hash_t)}; + +#endif /* PY_HASH_ALGORITHM == PY_HASH_FNV */ + + +#if PY_HASH_ALGORITHM == PY_HASH_SIPHASH24 +/* + Copyright (c) 2013 Marek Majkowski + + 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 THE + AUTHORS OR COPYRIGHT HOLDERS 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. + + + Original location: + https://github.com/majek/csiphash/ + + Solution inspired by code from: + Samuel Neves (supercop/crypto_auth/siphash24/little) + djb (supercop/crypto_auth/siphash24/little2) + Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c) + + Modified for Python by Christian Heimes: + - C89 / MSVC compatibility + - PY_UINT64_T, PY_UINT32_T and PY_UINT8_T + - _rotl64() on Windows +*/ + +typedef unsigned char PY_UINT8_T; + +/* The original code handles byte order. Python ignores the byte order here + * because don't aim for equal hash values across platforms and architectures. + */ +#define _le64toh(x) ((PY_UINT64_T)(x)) + +#ifdef _MSC_VER +#define ROTATE(x, b) _rotl64(x, b) +#else +#define ROTATE(x, b) (PY_UINT64_T)( ((x) << (b)) | ( (x) >> (64 - (b))) ) +#endif + +#define HALF_ROUND(a,b,c,d,s,t) \ + a += b; c += d; \ + b = ROTATE(b, s) ^ a; \ + d = ROTATE(d, t) ^ c; \ + a = ROTATE(a, 32); + +#define DOUBLE_ROUND(v0,v1,v2,v3) \ + HALF_ROUND(v0,v1,v2,v3,13,16); \ + HALF_ROUND(v2,v1,v0,v3,17,21); \ + HALF_ROUND(v0,v1,v2,v3,13,16); \ + HALF_ROUND(v2,v1,v0,v3,17,21); + + +static Py_hash_t +siphash24(const void *src, Py_ssize_t src_sz) { + PY_UINT64_T k0 = _le64toh(_Py_HashSecret.ui64.k0); + PY_UINT64_T k1 = _le64toh(_Py_HashSecret.ui64.k1); + PY_UINT64_T b = (PY_UINT64_T)src_sz << 56; + const PY_UINT64_T *in = (PY_UINT64_T*)src; + + PY_UINT64_T v0 = k0 ^ 0x736f6d6570736575ULL; + PY_UINT64_T v1 = k1 ^ 0x646f72616e646f6dULL; + PY_UINT64_T v2 = k0 ^ 0x6c7967656e657261ULL; + PY_UINT64_T v3 = k1 ^ 0x7465646279746573ULL; + + PY_UINT64_T t; + PY_UINT8_T *pt; + PY_UINT8_T *m; + + /* modified */ + if (src_sz == 0) { + return 0; + } + + while (src_sz >= 8) { + PY_UINT64_T mi = _le64toh(*in); + in += 1; + src_sz -= 8; + v3 ^= mi; + DOUBLE_ROUND(v0,v1,v2,v3); + v0 ^= mi; + } + + t = 0; + pt = (PY_UINT8_T *)&t; + m = (PY_UINT8_T *)in; + switch (src_sz) { + case 7: pt[6] = m[6]; + case 6: pt[5] = m[5]; + case 5: pt[4] = m[4]; + case 4: *((PY_UINT32_T*)&pt[0]) = *((PY_UINT32_T*)&m[0]); break; + case 3: pt[2] = m[2]; + case 2: pt[1] = m[1]; + case 1: pt[0] = m[0]; + } + b |= _le64toh(t); + + v3 ^= b; + DOUBLE_ROUND(v0,v1,v2,v3); + v0 ^= b; + v2 ^= 0xff; + DOUBLE_ROUND(v0,v1,v2,v3); + DOUBLE_ROUND(v0,v1,v2,v3); + + /* modified */ + t = (v0 ^ v1) ^ (v2 ^ v3); +#if SIZEOF_VOID_P == 4 + t ^= (t >> 32); +#endif + if (t == -1) { + return -2; + } + return (Py_hash_t)t; +} + +PyHash_FuncDef PyHash_Func = {siphash24, "siphash24", 64, 128}; + +#endif /* PY_HASH_ALGORITHM == PY_HASH_SIPHASH24 */ + +#ifdef __cplusplus +} +#endif diff -r 540a9c69c2ea -r 6a9fc0065458 Objects/memoryobject.c --- a/Objects/memoryobject.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Objects/memoryobject.c Sun Oct 06 16:48:10 2013 +0200 @@ -2742,7 +2742,7 @@ } /* Can't fail */ - self->hash = _Py_HashBytes((unsigned char *)mem, view->len); + self->hash = PyHash_Func.hash(mem, view->len); if (mem != view->buf) PyMem_Free(mem); diff -r 540a9c69c2ea -r 6a9fc0065458 Objects/object.c --- a/Objects/object.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Objects/object.c Sun Oct 06 16:48:10 2013 +0200 @@ -844,33 +844,6 @@ } Py_hash_t -_Py_HashBytes(unsigned char *p, Py_ssize_t len) -{ - Py_uhash_t x; - Py_ssize_t i; - - /* - We make the hash of the empty string be 0, rather than using - (prefix ^ suffix), since this slightly obfuscates the hash secret - */ -#ifdef Py_DEBUG - assert(_Py_HashSecret_Initialized); -#endif - if (len == 0) { - return 0; - } - x = (Py_uhash_t) _Py_HashSecret.prefix; - x ^= (Py_uhash_t) *p << 7; - for (i = 0; i < len; i++) - x = (_PyHASH_MULTIPLIER * x) ^ (Py_uhash_t) *p++; - x ^= (Py_uhash_t) len; - x ^= (Py_uhash_t) _Py_HashSecret.suffix; - if (x == -1) - x = -2; - return x; -} - -Py_hash_t PyObject_HashNotImplemented(PyObject *v) { PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'", @@ -878,8 +851,6 @@ return -1; } -_Py_HashSecret_t _Py_HashSecret; - Py_hash_t PyObject_Hash(PyObject *v) { diff -r 540a9c69c2ea -r 6a9fc0065458 Objects/unicodeobject.c --- a/Objects/unicodeobject.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Objects/unicodeobject.c Sun Oct 06 16:48:10 2013 +0200 @@ -11129,39 +11129,8 @@ _PyUnicode_HASH(self) = 0; return 0; } - - /* The hash function as a macro, gets expanded three times below. */ -#define HASH(P) \ - x ^= (Py_uhash_t) *P << 7; \ - while (--len >= 0) \ - x = (_PyHASH_MULTIPLIER * x) ^ (Py_uhash_t) *P++; \ - - x = (Py_uhash_t) _Py_HashSecret.prefix; - switch (PyUnicode_KIND(self)) { - case PyUnicode_1BYTE_KIND: { - const unsigned char *c = PyUnicode_1BYTE_DATA(self); - HASH(c); - break; - } - case PyUnicode_2BYTE_KIND: { - const Py_UCS2 *s = PyUnicode_2BYTE_DATA(self); - HASH(s); - break; - } - default: { - Py_UCS4 *l; - assert(PyUnicode_KIND(self) == PyUnicode_4BYTE_KIND && - "Impossible switch case in unicode_hash"); - l = PyUnicode_4BYTE_DATA(self); - HASH(l); - break; - } - } - x ^= (Py_uhash_t) PyUnicode_GET_LENGTH(self); - x ^= (Py_uhash_t) _Py_HashSecret.suffix; - - if (x == -1) - x = -2; + x = PyHash_Func.hash(PyUnicode_DATA(self), + PyUnicode_GET_LENGTH(self) * PyUnicode_KIND(self)); _PyUnicode_HASH(self) = x; return x; } diff -r 540a9c69c2ea -r 6a9fc0065458 Python/random.c --- a/Python/random.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Python/random.c Sun Oct 06 16:48:10 2013 +0200 @@ -95,7 +95,7 @@ /* Read size bytes from /dev/urandom into buffer. Call Py_FatalError() on error. */ static void -dev_urandom_noraise(char *buffer, Py_ssize_t size) +dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) { int fd; Py_ssize_t n; @@ -248,8 +248,9 @@ _PyRandom_Init(void) { char *env; - void *secret = &_Py_HashSecret; + unsigned char *secret = &_Py_HashSecret.uc16; Py_ssize_t secret_size = sizeof(_Py_HashSecret_t); + assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc16)); if (_Py_HashSecret_Initialized) return; @@ -277,17 +278,17 @@ memset(secret, 0, secret_size); } else { - lcg_urandom(seed, (unsigned char*)secret, secret_size); + lcg_urandom(seed, secret, secret_size); } } else { #ifdef MS_WINDOWS - (void)win32_urandom((unsigned char *)secret, secret_size, 0); + (void)win32_urandom(secret, secret_size, 0); #else /* #ifdef MS_WINDOWS */ # ifdef __VMS - vms_urandom((unsigned char *)secret, secret_size, 0); + vms_urandom(secret, secret_size, 0); # else - dev_urandom_noraise((char*)secret, secret_size); + dev_urandom_noraise(secret, secret_size); # endif #endif } diff -r 540a9c69c2ea -r 6a9fc0065458 Python/sysmodule.c --- a/Python/sysmodule.c Fri Sep 13 19:53:08 2013 +0200 +++ b/Python/sysmodule.c Sun Oct 06 16:48:10 2013 +0200 @@ -617,7 +617,7 @@ "hash_info\n\ \n\ A struct sequence providing parameters used for computing\n\ -numeric hashes. The attributes are read only."); +hashes. The attributes are read only."); static PyStructSequence_Field hash_info_fields[] = { {"width", "width of the type used for hashing, in bits"}, @@ -626,6 +626,10 @@ {"inf", "value to be used for hash of a positive infinity"}, {"nan", "value to be used for hash of a nan"}, {"imag", "multiplier used for the imaginary part of a complex number"}, + {"algorithm", "name of the algorithm for hashing of str, bytes and " + "memoryviews"}, + {"hash_bits", "internal output of hash algorithm"}, + {"seed_bits", "seed size of hash algorithm"}, {NULL, NULL} }; @@ -633,7 +637,7 @@ "sys.hash_info", hash_info_doc, hash_info_fields, - 5, + 8, }; static PyObject * @@ -654,6 +658,12 @@ PyLong_FromLong(_PyHASH_NAN)); PyStructSequence_SET_ITEM(hash_info, field++, PyLong_FromLong(_PyHASH_IMAG)); + PyStructSequence_SET_ITEM(hash_info, field++, + PyUnicode_FromString(PyHash_Func.name)); + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(PyHash_Func.hash_bits)); + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(PyHash_Func.seed_bits)); if (PyErr_Occurred()) { Py_CLEAR(hash_info); return NULL; @@ -1298,6 +1308,7 @@ executable -- absolute path of the executable binary of the Python interpreter\n\ float_info -- a struct sequence with information about the float implementation.\n\ float_repr_style -- string indicating the style of repr() output for floats\n\ +hash_info -- a struct sequenece with information about the hash algorithm.\n\ hexversion -- version information encoded as a single integer\n\ implementation -- Python implementation information.\n\ int_info -- a struct sequence with information about the int implementation.\n\ diff -r 540a9c69c2ea -r 6a9fc0065458 configure --- a/configure Fri Sep 13 19:53:08 2013 +0200 +++ b/configure Sun Oct 06 16:48:10 2013 +0200 @@ -792,6 +792,7 @@ enable_shared enable_profiling with_pydebug +with_hash_algorithm with_libs with_system_expat with_system_ffi @@ -1465,6 +1466,8 @@ compiler --with-suffix=.exe set executable suffix --with-pydebug build with Py_DEBUG defined + --with-hash-algorithm=[fnv|siphash24] + select hash algorithm --with-libs='lib1 ...' link against additional libs --with-system-expat build pyexpat module using an installed expat library @@ -8982,6 +8985,136 @@ *) ;; esac +# str, bytes and memoryview hash algorith + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-hash-algorithm" >&5 +$as_echo_n "checking for --with-hash-algorithm... " >&6; } + +# Check whether --with-hash_algorithm was given. +if test "${with_hash_algorithm+set}" = set; then : + withval=$with_hash_algorithm; +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 +$as_echo "$withval" >&6; } +case "$withval" in + fnv) + $as_echo "#define PY_HASH_ALGORITHM 0x464E56" >>confdefs.h + + ;; + siphash24) + $as_echo "#define PY_HASH_ALGORITHM 0x53495024" >>confdefs.h + + ;; + *) + as_fn_error $? "unknown hash algorithm '$withval'" "$LINENO" 5 + ;; +esac + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: default" >&5 +$as_echo "default" >&6; } +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + + # Most SVR4 platforms (e.g. Solaris) need -lsocket and -lnsl. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for t_open in -lnsl" >&5 $as_echo_n "checking for t_open in -lnsl... " >&6; } diff -r 540a9c69c2ea -r 6a9fc0065458 configure.ac --- a/configure.ac Fri Sep 13 19:53:08 2013 +0200 +++ b/configure.ac Sun Oct 06 16:48:10 2013 +0200 @@ -2224,6 +2224,34 @@ *) ;; esac +# str, bytes and memoryview hash algorith +AH_TEMPLATE(PY_HASH_ALGORITHM, + [Define hash algorithm for str, bytes and memoryview. + 0x53495024: SipHash24, 0x464E56: FNV]) + +AC_MSG_CHECKING(for --with-hash-algorithm) +dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output +AC_ARG_WITH(hash_algorithm, + AS_HELP_STRING([--with-hash-algorithm=@<:@fnv|siphash24@:>@], + [select hash algorithm]), +[ +AC_MSG_RESULT($withval) +case "$withval" in + fnv) + AC_DEFINE(PY_HASH_ALGORITHM, 0x464E56) + ;; + siphash24) + AC_DEFINE(PY_HASH_ALGORITHM, 0x53495024) + ;; + *) + AC_MSG_ERROR([unknown hash algorithm '$withval']) + ;; +esac +], +[AC_MSG_RESULT(default)]) + +AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) + # Most SVR4 platforms (e.g. Solaris) need -lsocket and -lnsl. AC_CHECK_LIB(nsl, t_open, [LIBS="-lnsl $LIBS"]) # SVR4 AC_CHECK_LIB(socket, socket, [LIBS="-lsocket $LIBS"], [], $LIBS) # SVR4 sockets diff -r 540a9c69c2ea -r 6a9fc0065458 pyconfig.h.in --- a/pyconfig.h.in Fri Sep 13 19:53:08 2013 +0200 +++ b/pyconfig.h.in Sun Oct 06 16:48:10 2013 +0200 @@ -1184,6 +1184,10 @@ /* Define to printf format modifier for Py_ssize_t */ #undef PY_FORMAT_SIZE_T +/* Define hash algorithm for str, bytes and memoryview. 0x53495024: SipHash24, + 0x464E56: FNV */ +#undef PY_HASH_ALGORITHM + /* Define if you want to build an interpreter with many run-time checks. */ #undef Py_DEBUG