aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/module.c
diff options
context:
space:
mode:
authorFrancois-Xavier Coudert <fxcoudert@gcc.gnu.org>2007-04-24 21:37:37 +0000
committerFrançois-Xavier Coudert <fxcoudert@gcc.gnu.org>2007-04-24 21:37:37 +0000
commit1e9ecf6da40abb1e294b71e60ae66ae34f93e0fd (patch)
tree7b803c93bd5afc3e3875d947014f635cef0ddad5 /gcc/fortran/module.c
parenta28f9a06027182195f2783b2518bea214bc4f730 (diff)
downloadgcc-1e9ecf6da40abb1e294b71e60ae66ae34f93e0fd.zip
gcc-1e9ecf6da40abb1e294b71e60ae66ae34f93e0fd.tar.gz
gcc-1e9ecf6da40abb1e294b71e60ae66ae34f93e0fd.tar.bz2
re PR fortran/31587 (Module files shouldn't be updated if their content doesn't change)
PR fortran/31587 * lib/gcc-dg.exp (scan-module): New function. * gfortran.dg/module_md5_1.f90: New test. * module.c (write_char): Add character to the MD5 buffer. (read_md5_from_module_file): New function. (gfc_dump_module): Compute MD5 for new module file. Call read_md5_from_module_file. Only overwrite old module file if the new MD5 is different. From-SVN: r124126
Diffstat (limited to 'gcc/fortran/module.c')
-rw-r--r--gcc/fortran/module.c99
1 files changed, 92 insertions, 7 deletions
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index af52ca9..03ad1a5 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -72,6 +72,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "arith.h"
#include "match.h"
#include "parse.h" /* FIXME */
+#include "md5.h"
#define MODULE_EXTENSION ".mod"
@@ -170,6 +171,9 @@ gfc_use_rename;
/* The FILE for the module we're reading or writing. */
static FILE *module_fp;
+/* MD5 context structure. */
+static struct md5_ctx ctx;
+
/* The name of the module we're reading (USE'ing) or writing. */
static char module_name[GFC_MAX_SYMBOL_LEN + 1];
@@ -1275,6 +1279,9 @@ write_char (char out)
if (fputc (out, module_fp) == EOF)
gfc_fatal_error ("Error writing modules file: %s", strerror (errno));
+ /* Add this to our MD5. */
+ md5_process_bytes (&out, sizeof (out), &ctx);
+
if (out != '\n')
module_column++;
else
@@ -3916,6 +3923,49 @@ write_module (void)
}
+/* Read a MD5 sum from the header of a module file. If the file cannot
+ be opened, or we have any other error, we return -1. */
+
+static int
+read_md5_from_module_file (const char * filename, unsigned char md5[16])
+{
+ FILE *file;
+ char buf[1024];
+ int n;
+
+ /* Open the file. */
+ if ((file = fopen (filename, "r")) == NULL)
+ return -1;
+
+ /* Read two lines. */
+ if (fgets (buf, sizeof (buf) - 1, file) == NULL
+ || fgets (buf, sizeof (buf) - 1, file) == NULL)
+ {
+ fclose (file);
+ return -1;
+ }
+
+ /* Close the file. */
+ fclose (file);
+
+ /* If the header is not what we expect, or is too short, bail out. */
+ if (strncmp (buf, "MD5:", 4) != 0 || strlen (buf) < 4 + 16)
+ return -1;
+
+ /* Now, we have a real MD5, read it into the array. */
+ for (n = 0; n < 16; n++)
+ {
+ unsigned int x;
+
+ if (sscanf (&(buf[4+2*n]), "%02x", &x) != 1)
+ return -1;
+
+ md5[n] = x;
+ }
+
+ return 0;
+}
+
/* Given module, dump it to disk. If there was an error while
processing the module, dump_flag will be set to zero and we delete
the module file, even if it was already there. */
@@ -3924,13 +3974,16 @@ void
gfc_dump_module (const char *name, int dump_flag)
{
int n;
- char *filename, *p;
+ char *filename, *filename_tmp, *p;
time_t now;
+ fpos_t md5_pos;
+ unsigned char md5_new[16], md5_old[16];
n = strlen (name) + strlen (MODULE_EXTENSION) + 1;
if (gfc_option.module_dir != NULL)
{
- filename = (char *) alloca (n + strlen (gfc_option.module_dir));
+ n += strlen (gfc_option.module_dir);
+ filename = (char *) alloca (n);
strcpy (filename, gfc_option.module_dir);
strcat (filename, name);
}
@@ -3941,26 +3994,41 @@ gfc_dump_module (const char *name, int dump_flag)
}
strcat (filename, MODULE_EXTENSION);
+ /* Name of the temporary file used to write the module. */
+ filename_tmp = (char *) alloca (n + 1);
+ strcpy (filename_tmp, filename);
+ strcat (filename_tmp, "0");
+
+ /* There was an error while processing the module. We delete the
+ module file, even if it was already there. */
if (!dump_flag)
{
unlink (filename);
return;
}
- module_fp = fopen (filename, "w");
+ /* Write the module to the temporary file. */
+ module_fp = fopen (filename_tmp, "w");
if (module_fp == NULL)
gfc_fatal_error ("Can't open module file '%s' for writing at %C: %s",
- filename, strerror (errno));
+ filename_tmp, strerror (errno));
+ /* Write the header, including space reserved for the MD5 sum. */
now = time (NULL);
p = ctime (&now);
*strchr (p, '\n') = '\0';
- fprintf (module_fp, "GFORTRAN module created from %s on %s\n",
+ fprintf (module_fp, "GFORTRAN module created from %s on %s\nMD5:",
gfc_source_file, p);
- fputs ("If you edit this, you'll get what you deserve.\n\n", module_fp);
+ fgetpos (module_fp, &md5_pos);
+ fputs ("00000000000000000000000000000000 -- "
+ "If you edit this, you'll get what you deserve.\n\n", module_fp);
+ /* Initialize the MD5 context that will be used for output. */
+ md5_init_ctx (&ctx);
+
+ /* Write the module itself. */
iomode = IO_OUTPUT;
strcpy (module_name, name);
@@ -3973,9 +4041,26 @@ gfc_dump_module (const char *name, int dump_flag)
write_char ('\n');
+ /* Write the MD5 sum to the header of the module file. */
+ md5_finish_ctx (&ctx, md5_new);
+ fsetpos (module_fp, &md5_pos);
+ for (n = 0; n < 16; n++)
+ fprintf (module_fp, "%02x", md5_new[n]);
+
if (fclose (module_fp))
gfc_fatal_error ("Error writing module file '%s' for writing: %s",
- filename, strerror (errno));
+ filename_tmp, strerror (errno));
+
+ /* Read the MD5 from the header of the old module file and compare. */
+ if (read_md5_from_module_file (filename, md5_old) != 0
+ || memcmp (md5_old, md5_new, sizeof (md5_old)) != 0)
+ {
+ /* Module file have changed, replace the old one. */
+ unlink (filename);
+ rename (filename_tmp, filename);
+ }
+ else
+ unlink (filename_tmp);
}