From 9ae3b6f0ff3626d7303488b9020eeeea811a4426 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 30 Jul 2004 13:21:40 +0000 Subject: [PATCH] More careful context hash calculation which doesn't depend on size of `unsigned long'. Should help Debian build problems (bug#259504). git-svn-id: svn://svn.tartarus.org/sgt/halibut@4377 cda61777-01e9-0310-a592-d414129be87e --- winhelp.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/winhelp.c b/winhelp.c index c41503d..ec36031 100644 --- a/winhelp.c +++ b/winhelp.c @@ -376,10 +376,6 @@ static unsigned long context_hash(char *context) "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF"; unsigned long hash; - /* Sanity check the size of unsigned long */ - enum { assertion = 1 / - (((unsigned long)0xFFFFFFFF) + 2 == (unsigned long)1) }; - /* * The hash algorithm starts the hash at 0 and updates it with * each character. Therefore, logically, the hash of an empty @@ -396,7 +392,38 @@ static unsigned long context_hash(char *context) */ hash = 0; while (*context) { - hash = hash * 43 + bytemapping[(unsigned char)*context]; + /* + * Be careful of overflowing `unsigned long', for maximum + * portability. + */ + + /* + * Multiply `hash' by 43. + */ + { + unsigned long bottom, top; + bottom = (hash & 0xFFFFUL) * 43; + top = ((hash >> 16) & 0xFFFFUL) * 43; + top += (bottom >> 16); + bottom &= 0xFFFFUL; + top &= 0xFFFFUL; + hash = (top << 16) | bottom; + } + + /* + * Add the mapping value for this byte to `hash'. + */ + { + int val = bytemapping[(unsigned char)*context]; + + if (val > 0 && hash > (0xFFFFFFFFUL - val)) { + hash -= (0xFFFFFFFFUL - val) + 1; + } else if (val < 0 && hash < -val) { + hash += (0xFFFFFFFFUL + val) + 1; + } else + hash += val; + } + context++; } return hash; -- 2.11.0