diff options
author | Janne Blomqvist <jb@gcc.gnu.org> | 2013-04-17 13:19:40 +0300 |
---|---|---|
committer | Janne Blomqvist <jb@gcc.gnu.org> | 2013-04-17 13:19:40 +0300 |
commit | 070edbc29c4f4a716cc6f4d9b038c9f38f9300a0 (patch) | |
tree | bdc067d3b77ecfbdb6d53c500ae6f5cefa3c906d /gcc/fortran/module.c | |
parent | 10a883113b6d5657efeb9d3eedef1a13f97185f3 (diff) | |
download | gcc-070edbc29c4f4a716cc6f4d9b038c9f38f9300a0.zip gcc-070edbc29c4f4a716cc6f4d9b038c9f38f9300a0.tar.gz gcc-070edbc29c4f4a716cc6f4d9b038c9f38f9300a0.tar.bz2 |
PR 40958 Compress module files with zlib.
frontend ChangeLog:
2013-04-17 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/40958
* scanner.h: New file.
* Make-lang.in: Dependencies on scanner.h.
* scanner.c (gfc_directorylist): Move to scanner.h.
* module.c: Don't include md5.h, include scanner.h and zlib.h.
(MOD_VERSION): Add comment about backwards compatibility.
(module_fp): Change type to gzFile.
(ctx): Remove.
(gzopen_included_file_1): New function.
(gzopen_included_file): New function.
(gzopen_intrinsic_module): New function.
(write_char): Use gzputc.
(read_crc32_from_module_file): New function.
(read_md5_from_module_file): Remove.
(gfc_dump_module): Use gz* functions instead of stdio, check gzip
crc32 instead of md5.
(read_module_to_tmpbuf): Use gz* functions instead of stdio.
(gfc_use_module): Use gz* functions.
testsuite ChangeLog:
2013-04-17 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/40958
* lib/gcc-dg.exp (scan-module): Uncompress module file before
scanning.
* gfortran.dg/module_md5_1.f90: Remove.
From-SVN: r198023
Diffstat (limited to 'gcc/fortran/module.c')
-rw-r--r-- | gcc/fortran/module.c | 224 |
1 files changed, 139 insertions, 85 deletions
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c index 046ba48..e6a4cd7 100644 --- a/gcc/fortran/module.c +++ b/gcc/fortran/module.c @@ -71,15 +71,18 @@ along with GCC; see the file COPYING3. If not see #include "arith.h" #include "match.h" #include "parse.h" /* FIXME */ -#include "md5.h" #include "constructor.h" #include "cpp.h" #include "tree.h" +#include "scanner.h" +#include <zlib.h> #define MODULE_EXTENSION ".mod" -/* Don't put any single quote (') in MOD_VERSION, - if yout want it to be recognized. */ +/* Don't put any single quote (') in MOD_VERSION, if you want it to be + recognized. + TODO: When the version is bumped, remove the extra empty line at + the beginning of module files. */ #define MOD_VERSION "10" @@ -180,11 +183,9 @@ pointer_info; /* Local variables */ -/* The FILE for the module we're reading or writing. */ -static FILE *module_fp; +/* The gzFile for the module we're reading or writing. */ +static gzFile module_fp; -/* MD5 context structure. */ -static struct md5_ctx ctx; /* The name of the module we're reading (USE'ing) or writing. */ static const char *module_name; @@ -976,6 +977,76 @@ free_true_name (true_name *t) /* Module reading and writing. */ +/* The following are versions similar to the ones in scanner.c, but + for dealing with compressed module files. */ + +static gzFile +gzopen_included_file_1 (const char *name, gfc_directorylist *list, + bool module, bool system) +{ + char *fullname; + gfc_directorylist *p; + gzFile f; + + for (p = list; p; p = p->next) + { + if (module && !p->use_for_modules) + continue; + + fullname = (char *) alloca(strlen (p->path) + strlen (name) + 1); + strcpy (fullname, p->path); + strcat (fullname, name); + + f = gzopen (fullname, "r"); + if (f != NULL) + { + if (gfc_cpp_makedep ()) + gfc_cpp_add_dep (fullname, system); + + return f; + } + } + + return NULL; +} + +static gzFile +gzopen_included_file (const char *name, bool include_cwd, bool module) +{ + gzFile f = NULL; + + if (IS_ABSOLUTE_PATH (name) || include_cwd) + { + f = gzopen (name, "r"); + if (f && gfc_cpp_makedep ()) + gfc_cpp_add_dep (name, false); + } + + if (!f) + f = gzopen_included_file_1 (name, include_dirs, module, false); + + return f; +} + +static gzFile +gzopen_intrinsic_module (const char* name) +{ + gzFile f = NULL; + + if (IS_ABSOLUTE_PATH (name)) + { + f = gzopen (name, "r"); + if (f && gfc_cpp_makedep ()) + gfc_cpp_add_dep (name, true); + } + + if (!f) + f = gzopen_included_file_1 (name, intrinsic_modules_dirs, true, true); + + return f; +} + + typedef enum { ATOM_NAME, ATOM_LPAREN, ATOM_RPAREN, ATOM_INTEGER, ATOM_STRING @@ -1463,12 +1534,9 @@ read_string (void) static void write_char (char out) { - if (putc (out, module_fp) == EOF) + if (gzputc (module_fp, out) == EOF) gfc_fatal_error ("Error writing modules file: %s", xstrerror (errno)); - /* Add this to our MD5. */ - md5_process_bytes (&out, sizeof (out), &ctx); - if (out != '\n') module_column++; else @@ -5407,61 +5475,47 @@ 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. */ +/* Read a CRC32 sum from the gzip trailer of a module file. Returns + true on success, false on failure. */ -static int -read_md5_from_module_file (const char * filename, unsigned char md5[16]) +static bool +read_crc32_from_module_file (const char* filename, uLong* crc) { FILE *file; - char buf[1024]; - int n; + char buf[4]; + unsigned int val; - /* Open the file. */ - if ((file = fopen (filename, "r")) == NULL) - return -1; + /* Open the file in binary mode. */ + if ((file = fopen (filename, "rb")) == NULL) + return false; - /* Read the first line. */ - if (fgets (buf, sizeof (buf) - 1, file) == NULL) + /* The gzip crc32 value is found in the [END-8, END-4] bytes of the + file. See RFC 1952. */ + if (fseek (file, -8, SEEK_END) != 0) { fclose (file); - return -1; + return false; } - /* The file also needs to be overwritten if the version number changed. */ - n = strlen ("GFORTRAN module version '" MOD_VERSION "' created"); - if (strncmp (buf, "GFORTRAN module version '" MOD_VERSION "' created", n) != 0) + /* Read the CRC32. */ + if (fread (buf, 1, 4, file) != 4) { fclose (file); - return -1; - } - - /* Read a second line. */ - if (fgets (buf, sizeof (buf) - 1, file) == NULL) - { - fclose (file); - return -1; + return false; } /* 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; - } + val = (buf[0] & 0xFF) + ((buf[1] & 0xFF) << 8) + ((buf[2] & 0xFF) << 16) + + ((buf[3] & 0xFF) << 24); + *crc = val; + + /* For debugging, the CRC value printed in hexadecimal should match + the CRC printed by "zcat -l -v filename". + printf("CRC of file %s is %x\n", filename, val); */ - return 0; + return true; } @@ -5474,8 +5528,7 @@ gfc_dump_module (const char *name, int dump_flag) { int n; char *filename, *filename_tmp; - fpos_t md5_pos; - unsigned char md5_new[16], md5_old[16]; + uLong crc, crc_old; n = strlen (name) + strlen (MODULE_EXTENSION) + 1; if (gfc_option.module_dir != NULL) @@ -5509,20 +5562,18 @@ gfc_dump_module (const char *name, int dump_flag) gfc_cpp_add_target (filename); /* Write the module to the temporary file. */ - module_fp = fopen (filename_tmp, "w"); + module_fp = gzopen (filename_tmp, "w"); if (module_fp == NULL) gfc_fatal_error ("Can't open module file '%s' for writing at %C: %s", filename_tmp, xstrerror (errno)); - /* Write the header, including space reserved for the MD5 sum. */ - fprintf (module_fp, "GFORTRAN module version '%s' created from %s\n" - "MD5:", MOD_VERSION, gfc_source_file); - fgetpos (module_fp, &md5_pos); - fputs ("00000000000000000000000000000000 -- " - "If you edit this, you'll get what you deserve.\n\n", module_fp); + /* Write the header. + FIXME: For backwards compatibility with the old uncompressed + module format, write an extra empty line. When the module version + is bumped, this can be removed. */ + gzprintf (module_fp, "GFORTRAN module version '%s' created from %s\n\n", + MOD_VERSION, gfc_source_file); - /* Initialize the MD5 context that will be used for output. */ - md5_init_ctx (&ctx); /* Write the module itself. */ iomode = IO_OUTPUT; @@ -5537,24 +5588,17 @@ 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)) + if (gzclose (module_fp)) gfc_fatal_error ("Error writing module file '%s' for writing: %s", filename_tmp, xstrerror (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) + /* Read the CRC32 from the gzip trailers of the module files and + compare. */ + if (!read_crc32_from_module_file (filename_tmp, &crc) + || !read_crc32_from_module_file (filename, &crc_old) + || crc_old != crc) { /* Module file have changed, replace the old one. */ - if (unlink (filename) && errno != ENOENT) - gfc_fatal_error ("Can't delete module file '%s': %s", filename, - xstrerror (errno)); if (rename (filename_tmp, filename)) gfc_fatal_error ("Can't rename module file '%s' to '%s': %s", filename_tmp, filename, xstrerror (errno)); @@ -6023,17 +6067,27 @@ create_derived_type (const char *name, const char *modname, static void read_module_to_tmpbuf () { - /* Find out the size of the file and reserve space. Assume we're at - the beginning. */ - fseek (module_fp, 0, SEEK_END); - long file_size = ftell (module_fp); - fseek (module_fp, 0, SEEK_SET); + /* We don't know the uncompressed size, so enlarge the buffer as + needed. */ + int cursz = 4096; + int rsize = cursz; + int len = 0; + + module_content = XNEWVEC (char, cursz); - /* An extra byte for the terminating NULL. */ - module_content = XNEWVEC (char, file_size + 1); + while (1) + { + int nread = gzread (module_fp, module_content + len, rsize); + len += nread; + if (nread < rsize) + break; + cursz *= 2; + module_content = XRESIZEVEC (char, module_content, cursz); + rsize = cursz - len; + } - fread (module_content, 1, file_size, module_fp); - module_content[file_size] = '\0'; + module_content = XRESIZEVEC (char, module_content, len + 1); + module_content[len] = '\0'; module_pos = 0; } @@ -6254,7 +6308,7 @@ gfc_use_module (gfc_use_list *module) specified that the module is intrinsic. */ module_fp = NULL; if (!module->intrinsic) - module_fp = gfc_open_included_file (filename, true, true); + module_fp = gzopen_included_file (filename, true, true); /* Then, see if it's an intrinsic one, unless the USE statement specified that the module is non-intrinsic. */ @@ -6283,7 +6337,7 @@ gfc_use_module (gfc_use_list *module) return; } - module_fp = gfc_open_intrinsic_module (filename); + module_fp = gzopen_intrinsic_module (filename); if (module_fp == NULL && module->intrinsic) gfc_fatal_error ("Can't find an intrinsic module named '%s' at %C", @@ -6308,7 +6362,7 @@ gfc_use_module (gfc_use_list *module) start = 0; read_module_to_tmpbuf (); - fclose (module_fp); + gzclose (module_fp); /* Skip the first two lines of the module, after checking that this is a gfortran module file. */ |