X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fjcf-io.c;h=28a48bb4504dc94af3627a91d13bd001d5e73e3f;hb=b22f66e203c5928a518440558634496a4ff1b391;hp=869bc002da65cd3b984b863e5fdf4a703adf2ee8;hpb=d9f14ffe246a44085f7c91fb767312653ed491d2;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/jcf-io.c b/gcc/java/jcf-io.c index 869bc002da6..28a48bb4504 100644 --- a/gcc/java/jcf-io.c +++ b/gcc/java/jcf-io.c @@ -1,20 +1,22 @@ /* Utility routines for finding and reading Java(TM) .class files. - Copyright (C) 1996, 97-98, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009 Free Software Foundation, Inc. -This program is free software; you can redistribute it and/or modify +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 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. -This program is distributed in the hope that it will be useful, +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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. +along with GCC; see the file COPYING3. If not see +. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. @@ -24,11 +26,17 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "jcf.h" #include "tree.h" #include "toplev.h" #include "java-tree.h" +#include "hashtab.h" +#include + +#include "zlib.h" /* DOS brain-damage */ #ifndef O_BINARY @@ -36,8 +44,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #endif int -DEFUN(jcf_unexpected_eof, (jcf, count), - JCF *jcf AND int count ATTRIBUTE_UNUSED) +jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED) { if (jcf->filename) fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename); @@ -47,8 +54,7 @@ DEFUN(jcf_unexpected_eof, (jcf, count), } void -DEFUN(jcf_trim_old_input, (jcf), - JCF *jcf) +jcf_trim_old_input (JCF *jcf) { int count = jcf->read_ptr - jcf->buffer; if (count > 0) @@ -60,8 +66,7 @@ DEFUN(jcf_trim_old_input, (jcf), } int -DEFUN(jcf_filbuf_from_stdio, (jcf, count), - JCF *jcf AND int count) +jcf_filbuf_from_stdio (JCF *jcf, int count) { FILE *file = (FILE*) (jcf->read_state); if (count > jcf->buffer_end - jcf->read_ptr) @@ -70,8 +75,9 @@ DEFUN(jcf_filbuf_from_stdio, (jcf, count), JCF_u4 old_read_end = jcf->read_end - jcf->buffer; JCF_u4 old_size = jcf->buffer_end - jcf->buffer; JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count; - unsigned char *new_buffer = jcf->buffer == NULL ? ALLOC (new_size) - : REALLOC (jcf->buffer, new_size); + unsigned char *new_buffer + = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size) + : XRESIZEVAR (unsigned char, jcf->buffer, new_size); jcf->buffer = new_buffer; jcf->buffer_end = new_buffer + new_size; jcf->read_ptr = new_buffer + old_read_ptr; @@ -88,7 +94,7 @@ DEFUN(jcf_filbuf_from_stdio, (jcf, count), #include "zipfile.h" -struct ZipFileCache *SeenZipFiles = NULL; +struct ZipFile *SeenZipFiles = NULL; /* Open a zip file with the given name, and cache directory and file descriptor. If the file is missing, treat it as an empty archive. @@ -96,43 +102,51 @@ struct ZipFileCache *SeenZipFiles = NULL; */ ZipFile * -DEFUN(opendir_in_zip, (zipfile, is_system), - const char *zipfile AND int is_system) +opendir_in_zip (const char *zipfile, int is_system) { - struct ZipFileCache* zipf; + struct ZipFile* zipf; char magic [4]; int fd; for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next) { if (strcmp (zipf->name, zipfile) == 0) - return &zipf->z; + return zipf; } - zipf = ALLOC (sizeof (struct ZipFileCache) + strlen (zipfile) + 1); + zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1); zipf->next = SeenZipFiles; zipf->name = (char*)(zipf+1); strcpy (zipf->name, zipfile); - SeenZipFiles = zipf; fd = open (zipfile, O_RDONLY | O_BINARY); - zipf->z.fd = fd; + zipf->fd = fd; if (fd < 0) { /* A missing zip file is not considered an error. We may want to re-consider that. FIXME. */ - zipf->z.count = 0; - zipf->z.dir_size = 0; - zipf->z.central_directory = NULL; + zipf->count = 0; + zipf->dir_size = 0; + zipf->central_directory = NULL; } else { jcf_dependency_add_file (zipfile, is_system); if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC) - return NULL; + { + free (zipf); + close (fd); + return NULL; + } lseek (fd, 0L, SEEK_SET); - if (read_zip_archive (&zipf->z) != 0) - return NULL; + if (read_zip_archive (zipf) != 0) + { + free (zipf); + close (fd); + return NULL; + } } - return &zipf->z; + + SeenZipFiles = zipf; + return zipf; } /* Returns: @@ -142,9 +156,8 @@ DEFUN(opendir_in_zip, (zipfile, is_system), */ int -DEFUN(open_in_zip, (jcf, zipfile, zipmember, is_system), - JCF *jcf AND const char *zipfile AND const char *zipmember - AND int is_system) +open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember, + int is_system) { ZipDirectory *zipd; int i, len; @@ -165,48 +178,66 @@ DEFUN(open_in_zip, (jcf, zipfile, zipmember, is_system), strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0) { JCF_ZERO (jcf); - jcf->buffer = ALLOC (zipd->size); - jcf->buffer_end = jcf->buffer + zipd->size; - jcf->read_ptr = jcf->buffer; - jcf->read_end = jcf->buffer_end; - jcf->filbuf = jcf_unexpected_eof; + jcf->filename = xstrdup (zipfile); jcf->classname = xstrdup (zipmember); - jcf->zipd = (void *)zipd; - if (lseek (zipf->fd, zipd->filestart, 0) < 0 - || read (zipf->fd, jcf->buffer, zipd->size) != zipd->size) - return -2; - return 0; + return read_zip_member(jcf, zipd, zipf); } } return -1; } -#if JCF_USE_STDIO -char* -DEFUN(open_class, (filename, jcf, stream, dep_name), - char *filename AND JCF *jcf AND FILE* stream AND const char *dep_name) +/* Read data from zip archive member. */ + +int +read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf) { - if (jcf) + jcf->filbuf = jcf_unexpected_eof; + jcf->zipd = zipd; + + if (zipd->compression_method == Z_NO_COMPRESSION) { - if (dep_name != NULL) - jcf_dependency_add_file (dep_name, 0); - JCF_ZERO (jcf); - jcf->buffer = NULL; - jcf->buffer_end = NULL; - jcf->read_ptr = NULL; - jcf->read_end = NULL; - jcf->read_state = stream; - jcf->filbuf = jcf_filbuf_from_stdio; + jcf->buffer = XNEWVEC (unsigned char, zipd->size); + jcf->buffer_end = jcf->buffer + zipd->size; + jcf->read_ptr = jcf->buffer; + jcf->read_end = jcf->buffer_end; + if (lseek (zipf->fd, zipd->filestart, 0) < 0 + || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size) + return -2; } else - fclose (stream); - return filename; + { + char *buffer; + z_stream d_stream; /* decompression stream */ + d_stream.zalloc = (alloc_func) 0; + d_stream.zfree = (free_func) 0; + d_stream.opaque = (voidpf) 0; + + jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size); + d_stream.next_out = jcf->buffer; + d_stream.avail_out = zipd->uncompressed_size; + jcf->buffer_end = jcf->buffer + zipd->uncompressed_size; + jcf->read_ptr = jcf->buffer; + jcf->read_end = jcf->buffer_end; + buffer = XNEWVEC (char, zipd->size); + d_stream.next_in = (unsigned char *) buffer; + d_stream.avail_in = zipd->size; + if (lseek (zipf->fd, zipd->filestart, 0) < 0 + || read (zipf->fd, buffer, zipd->size) != (long) zipd->size) + return -2; + /* Handle NO_HEADER using undocumented zlib feature. + This is a very common hack. */ + inflateInit2 (&d_stream, -MAX_WBITS); + inflate (&d_stream, Z_NO_FLUSH); + inflateEnd (&d_stream); + free (buffer); + } + + return 0; } -#else -char* -DEFUN(open_class, (filename, jcf, fd, dep_name), - char *filename AND JCF *jcf AND int fd AND const char *dep_name) + +const char * +open_class (const char *filename, JCF *jcf, int fd, const char *dep_name) { if (jcf) { @@ -220,12 +251,12 @@ DEFUN(open_class, (filename, jcf, fd, dep_name), if (dep_name != NULL) jcf_dependency_add_file (dep_name, 0); JCF_ZERO (jcf); - jcf->buffer = ALLOC (stat_buf.st_size); + jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size); jcf->buffer_end = jcf->buffer + stat_buf.st_size; jcf->read_ptr = jcf->buffer; jcf->read_end = jcf->buffer_end; jcf->read_state = NULL; - jcf->filename = filename; + jcf->filename = xstrdup (filename); if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size) { perror ("Failed to read .class file"); @@ -238,61 +269,74 @@ DEFUN(open_class, (filename, jcf, fd, dep_name), close (fd); return filename; } -#endif const char * -DEFUN(find_classfile, (filename, jcf, dep_name), - char *filename AND JCF *jcf AND const char *dep_name) +find_classfile (char *filename, JCF *jcf, const char *dep_name) { -#if JCF_USE_STDIO - FILE *stream = fopen (filename, "rb"); - if (stream == NULL) - return NULL; - return open_class (arg, jcf, stream, dep_name); -#else int fd = open (filename, O_RDONLY | O_BINARY); if (fd < 0) return NULL; return open_class (filename, jcf, fd, dep_name); -#endif } +/* Returns 1 if the CLASSNAME (really a char *) matches the name + stored in TABLE_ENTRY (also a char *). */ + +static int +memoized_class_lookup_eq (const void *table_entry, const void *classname) +{ + return strcmp ((const char *)classname, (const char *)table_entry) == 0; +} + +/* A hash table keeping track of class names that were not found + during class lookup. (There is no need to cache the values + associated with names that were found; they are saved in + IDENTIFIER_CLASS_VALUE.) */ +static htab_t memoized_class_lookups; + /* Returns a freshly malloc'd string with the fully qualified pathname - of the .class file for the class CLASSNAME. Returns NULL on - failure. If JCF != NULL, it is suitably initialized. - SOURCE_OK is true if we should also look for .java file. */ + of the .class file for the class CLASSNAME. CLASSNAME must be + allocated in permanent storage; this function may retain a pointer + to it. Returns NULL on failure. If JCF != NULL, it is suitably + initialized. SOURCE_OK is true if we should also look for .java + file. */ const char * -DEFUN(find_class, (classname, classname_length, jcf, source_ok), - const char *classname AND int classname_length AND JCF *jcf AND int source_ok) - +find_class (const char *classname, int classname_length, JCF *jcf) { -#if JCF_USE_STDIO - FILE *stream; -#else int fd; -#endif - int i, k, java = -1, class = -1; - struct stat java_buf, class_buf; + int i, k, klass = -1; + struct stat class_buf; char *dep_file; void *entry; - char *java_buffer; + int buflen; + char *buffer; + hashval_t hash; + + /* Create the hash table, if it does not already exist. */ + if (!memoized_class_lookups) + memoized_class_lookups = htab_create (37, + htab_hash_string, + memoized_class_lookup_eq, + NULL); + + /* Loop for this class in the hashtable. If it is present, we've + already looked for this class and failed to find it. */ + hash = htab_hash_string (classname); + if (htab_find_with_hash (memoized_class_lookups, classname, hash)) + return NULL; /* Allocate and zero out the buffer, since we don't explicitly put a null pointer when we're copying it below. */ - int buflen = jcf_path_max_len () + classname_length + 10; - char *buffer = (char *) ALLOC (buflen); - bzero (buffer, buflen); - - java_buffer = (char *) alloca (buflen); - - jcf->java_source = 0; + buflen = jcf_path_max_len () + classname_length + 10; + buffer = XNEWVAR (char, buflen); + memset (buffer, 0, buflen); for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry)) { const char *path_name = jcf_path_name (entry); - if (class != 0) + if (klass != 0) { int dir_len; @@ -335,123 +379,40 @@ DEFUN(find_class, (classname, classname_length, jcf, source_ok), else continue; } - class = stat (buffer, &class_buf); + klass = stat (buffer, &class_buf); } - - if (source_ok) - { - /* Compute name of .java file. */ - int l, m; - strcpy (java_buffer, path_name); - l = strlen (java_buffer); - for (m = 0; m < classname_length; ++m) - java_buffer[m + l] = (classname[m] == '.' ? '/' : classname[m]); - strcpy (java_buffer + m + l, ".java"); - java = stat (java_buffer, &java_buf); - if (java == 0) - break; - } - } - - /* We preferably pick a class file if we have a chance. If the source - file is newer than the class file, we issue a warning and parse the - source file instead. - There should be a flag to allow people have the class file picked - up no matter what. FIXME. */ - if (! java && ! class && java_buf.st_mtime >= class_buf.st_mtime) - { - char *stripped_class_name = xstrdup (classname); - int i = strlen (stripped_class_name); - - while (stripped_class_name [i] != '.') - i--; - - stripped_class_name [i] = '\0'; - warning ("Source file for class `%s' is newer than its matching class file. Source file used instead", stripped_class_name); - free (stripped_class_name); - class = -1; } - if (! java) - dep_file = java_buffer; - else - dep_file = buffer; -#if JCF_USE_STDIO - if (!class) - { - SOURCE_FRONTEND_DEBUG (("Trying %s", buffer)); - stream = fopen (buffer, "rb"); - if (stream) - goto found; - } - /* Give .java a try, if necessary */ - if (!java) - { - strcpy (buffer, java_buffer); - SOURCE_FRONTEND_DEBUG (("Trying %s", buffer)); - stream = fopen (buffer, "r"); - if (stream) - { - jcf->java_source = 1; - goto found; - } - } -#else - if (!class) + dep_file = buffer; + if (!klass) { SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n", classname+classname_length- (classname_length <= 30 ? classname_length : 30))); - fd = open (buffer, O_RDONLY | O_BINARY); + fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY); if (fd >= 0) goto found; } - /* Give .java a try, if necessary */ - if (!java) - { - strcpy (buffer, java_buffer); - SOURCE_FRONTEND_DEBUG ((stderr, "[Source selected: %s]\n", - classname+classname_length- - (classname_length <= 30 ? - classname_length : 30))); - fd = open (buffer, O_RDONLY); - if (fd >= 0) - { - jcf->java_source = 1; - goto found; - } - } -#endif free (buffer); + + /* Remember that this class could not be found so that we do not + have to look again. */ + *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT) + = (void *) CONST_CAST (char *, classname); + return NULL; found: -#if JCF_USE_STDIO - if (jcf->java_source) - return NULL; /* FIXME */ - else - return open_class (buffer, jcf, stream, dep_file); -#else - if (jcf->java_source) - { - JCF_ZERO (jcf); /* JCF_FINISH relies on this */ - jcf->java_source = 1; - jcf->filename = xstrdup (buffer); - close (fd); /* We use STDIO for source file */ - } - else - buffer = open_class (buffer, jcf, fd, dep_file); - jcf->classname = (char *) ALLOC (classname_length + 1); - strncpy (jcf->classname, classname, classname_length + 1); - jcf->classname = xstrdup (classname); - return buffer; -#endif + { + const char *const tmp = open_class (buffer, jcf, fd, dep_file); + jcf->classname = xstrdup (classname); + return tmp; + } } void -DEFUN(jcf_print_char, (stream, ch), - FILE *stream AND int ch) +jcf_print_char (FILE *stream, int ch) { switch (ch) { @@ -482,8 +443,7 @@ DEFUN(jcf_print_char, (stream, ch), /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */ void -DEFUN(jcf_print_utf8, (stream, str, length), - FILE *stream AND register const unsigned char *str AND int length) +jcf_print_utf8 (FILE *stream, const unsigned char *str, int length) { const unsigned char * limit = str + length; while (str < limit) @@ -501,9 +461,8 @@ DEFUN(jcf_print_utf8, (stream, str, length), /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */ void -DEFUN(jcf_print_utf8_replace, (stream, str, length, in_char, out_char), - FILE *stream AND const unsigned char *str AND int length - AND int in_char AND int out_char) +jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length, + int in_char, int out_char) { const unsigned char *limit = str + length; while (str < limit) @@ -520,11 +479,12 @@ DEFUN(jcf_print_utf8_replace, (stream, str, length, in_char, out_char), /* Check that all the cross-references in the constant pool are valid. Returns 0 on success. - Otherwise, returns the index of the (first) invalid entry. */ + Otherwise, returns the index of the (first) invalid entry. + Only checks internal consistency, but does not check that + any classes, fields, or methods are valid.*/ int -DEFUN(verify_constant_pool, (jcf), - JCF *jcf) +verify_constant_pool (JCF *jcf) { int i, n; for (i = 1; i < JPOOL_SIZE (jcf); i++) @@ -573,12 +533,11 @@ DEFUN(verify_constant_pool, (jcf), } void -DEFUN(format_uint, (buffer, value, base), - char *buffer AND uint64 value AND int base) +format_uint (char *buffer, uint64 value, int base) { #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8) char buf[WRITE_BUF_SIZE]; - register char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */ + char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */ int chars_written; int i; @@ -586,7 +545,7 @@ DEFUN(format_uint, (buffer, value, base), /* Note this code does not pretend to be optimized. */ do { int digit = value % base; - static char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; *--buf_ptr = digit_chars[digit]; value /= base; } while (value != 0); @@ -598,8 +557,7 @@ DEFUN(format_uint, (buffer, value, base), } void -DEFUN(format_int, (buffer, value, base), - char *buffer AND jlong value AND int base) +format_int (char *buffer, jlong value, int base) { uint64 abs_value; if (value < 0)