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 | |
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')
-rw-r--r-- | gcc/fortran/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/fortran/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/fortran/module.c | 224 | ||||
-rw-r--r-- | gcc/fortran/scanner.c | 12 | ||||
-rw-r--r-- | gcc/fortran/scanner.h | 32 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/module_md5_1.f90 | 13 | ||||
-rw-r--r-- | gcc/testsuite/lib/gcc-dg.exp | 2 |
8 files changed, 204 insertions, 109 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 2f99025..af13708 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,24 @@ +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. + 2013-04-16 Tobias Burnus <burnus@net-b.de> PR fortran/39505 diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in index 8c9e7ea..5ce2a24 100644 --- a/gcc/fortran/Make-lang.in +++ b/gcc/fortran/Make-lang.in @@ -369,3 +369,5 @@ fortran/resolve.o: fortran/dependency.h fortran/data.h fortran/target-memory.h fortran/data.o: fortran/data.h fortran/options.o: $(PARAMS_H) $(TARGET_H) fortran/cpp.h fortran/cpp.o: fortran/cpp.c incpath.h incpath.o cppbuiltin.h +fortran/scanner.o: fortran/scanner.h +fortran/module.o: fortran/scanner.h 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. */ diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c index fd8f284..882e2d5 100644 --- a/gcc/fortran/scanner.c +++ b/gcc/fortran/scanner.c @@ -48,18 +48,10 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "flags.h" #include "cpp.h" - -/* Structure for holding module and include file search path. */ -typedef struct gfc_directorylist -{ - char *path; - bool use_for_modules; - struct gfc_directorylist *next; -} -gfc_directorylist; +#include "scanner.h" /* List of include file search directories. */ -static gfc_directorylist *include_dirs, *intrinsic_modules_dirs; +gfc_directorylist *include_dirs, *intrinsic_modules_dirs; static gfc_file *file_head, *current_file; diff --git a/gcc/fortran/scanner.h b/gcc/fortran/scanner.h new file mode 100644 index 0000000..4c559fb --- /dev/null +++ b/gcc/fortran/scanner.h @@ -0,0 +1,32 @@ +/* Character scanner header. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Janne Blomqvist + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + + +/* Structure for holding module and include file search path. */ +typedef struct gfc_directorylist +{ + char *path; + bool use_for_modules; + struct gfc_directorylist *next; +} +gfc_directorylist; + +/* List of include file search directories. */ +extern gfc_directorylist *include_dirs, *intrinsic_modules_dirs; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d9a432c..7bfc68d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +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. + 2013-04-16 Naveen H.S <Naveen.Hurugalawadi@caviumnetworks.com> * gcc.target/aarch64/adds3.c: New. diff --git a/gcc/testsuite/gfortran.dg/module_md5_1.f90 b/gcc/testsuite/gfortran.dg/module_md5_1.f90 deleted file mode 100644 index 1f522cb..0000000 --- a/gcc/testsuite/gfortran.dg/module_md5_1.f90 +++ /dev/null @@ -1,13 +0,0 @@ -! Check that we can write a module file, that it has a correct MD5 sum, -! and that we can read it back. -! -! { dg-do compile } -module foo - integer(kind=4), parameter :: pi = 3_4 -end module foo - -program test - use foo - print *, pi -end program test -! { dg-final { scan-module "foo" "MD5:510304affe70481794fecdb22fc9ca0c" } } diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 3a612a5..f64f4a1 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -633,7 +633,7 @@ proc cleanup-saved-temps { args } { # Argument 1 is the regexp to match proc scan-module { args } { set modfilename [string tolower [lindex $args 0]].mod - set fd [open $modfilename r] + set fd [open [list | gzip -dc $modfilename] r] set text [read $fd] close $fd |