--- module.c.orig 2005-07-24 09:21:32.000000000 +0800 +++ module.c 2005-08-05 15:10:17.000000000 +0800 @@ -27,6 +27,7 @@ 02111-1307, USA. */ #include "gpc.h" +#include "timevar.h" #include "p/version.h" #ifdef EGCS @@ -105,7 +106,8 @@ static char *locate_file_1 (const char *, const char *); static const char *get_automake_switches (int); static struct interface_table_t *get_interface_table (tree, tree); -static gpi_int compute_checksum (unsigned char *, gpi_int); +static gpi_int compute_checksum_old (unsigned char *, gpi_int); +static gpi_int compute_checksum_new (unsigned char *, gpi_int); static int itab_check_gpi_checksum (tree, gpi_int, int); static const char *file_basename (const char *); static int find_automake_tempfile_entry (const char *, const char *, int); @@ -1744,7 +1748,7 @@ } /* Write chunk to file */ - checksum = compute_checksum (wb.outbuf, wb.outbufcount); + checksum = compute_checksum_new (wb.outbuf, wb.outbufcount); itab_check_gpi_checksum (name, checksum, 1); start_chunk (s, GPI_CHUNK_NODES, wb.outbufcount + sizeof (checksum)); store_length_f (s, wb.outbuf, wb.outbufcount); @@ -2345,13 +2357,72 @@ } /* Compute a checksum for a GPI file. - @@ Simple weighted sum. Perhaps we should use MD5 or something. */ + @@ Simple weighted sum. Unrolled. Watch out for performance. */ +static gpi_int +compute_checksum_old (unsigned char *buf, gpi_int size) +{ + gpi_int sum = 0, n = 0; + + while ( size > 4 ) { + sum += n * buf[n]; + n++; + sum += n * buf[n]; + n++; + sum += n * buf[n]; + n++; + sum += n * buf[n]; + n++; + size -= 4; + } + while ( size > 0 ) { + sum += n * buf[n]; + n++; + size--; + } + return sum; +} + + +/* Compute a checksum for a GPI file. + @@ Shifted sum. Watch out for performance. */ static gpi_int -compute_checksum (unsigned char *buf, gpi_int size) +compute_checksum_new (unsigned char *buf, gpi_int size) { - gpi_int sum = 0, n; - for (n = 0; n < size; n++) - sum += n * buf[n]; + gpi_int sum = 0, n = 0; + + if ( size > 0x7fffffff || sizeof(int) < 4) { + for (n = 0; n < size; n++) + sum += n * buf[n]; + } else { + int ni = 0; + int sizei = size; + int sumi = 0; + while ( sizei > 8 ) { + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sumi += (int)buf[ni]; + ni++; + sizei -= 8; + } + while ( sizei > 0 ) { + sumi += (int)buf[ni]; + ni++; + sizei--; + } + sum = sumi; + } return sum; } @@ -3392,7 +3463,8 @@ mseek (gpi_file, start_of_nodes + size_of_nodes - sizeof (checksum)); LOAD_ANY_F (gpi_file, checksum); mseek (gpi_file, oldpos); - if (compute_checksum (mptr (gpi_file, start_of_nodes), size_of_nodes - sizeof (checksum)) != checksum) + if (compute_checksum_new (mptr (gpi_file, start_of_nodes), size_of_nodes - sizeof (checksum)) != checksum + && compute_checksum_old (mptr (gpi_file, start_of_nodes), size_of_nodes - sizeof (checksum)) != checksum) { error ("%s: checksum mismatch (GPI file corrupt)", current_gpi_file_name); exit (FATAL_EXIT_CODE);