diff options
Diffstat (limited to 'gcc-4.2.1/gcc/java/jcf-io.c')
-rw-r--r-- | gcc-4.2.1/gcc/java/jcf-io.c | 762 |
1 files changed, 0 insertions, 762 deletions
diff --git a/gcc-4.2.1/gcc/java/jcf-io.c b/gcc-4.2.1/gcc/java/jcf-io.c deleted file mode 100644 index c8651b671..000000000 --- a/gcc-4.2.1/gcc/java/jcf-io.c +++ /dev/null @@ -1,762 +0,0 @@ -/* Utility routines for finding and reading Java(TM) .class files. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. - -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) -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 COPYING. If not, write to -the Free Software Foundation, 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. - -Java and all Java-based marks are trademarks or registered trademarks -of Sun Microsystems, Inc. in the United States and other countries. -The Free Software Foundation is independent of Sun Microsystems, Inc. */ - -/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */ - -#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" -#if JCF_USE_SCANDIR -#include <dirent.h> -#include <fnmatch.h> -#endif - -#include "zlib.h" - -/* DOS brain-damage */ -#ifndef O_BINARY -#define O_BINARY 0 /* MS-DOS brain-damage */ -#endif - -int -jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED) -{ - if (jcf->filename) - fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename); - else - fprintf (stderr, "Premature end of .class file <stdin>.\n"); - exit (-1); -} - -void -jcf_trim_old_input (JCF *jcf) -{ - int count = jcf->read_ptr - jcf->buffer; - if (count > 0) - { - memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr); - jcf->read_ptr -= count; - jcf->read_end -= count; - } -} - -int -jcf_filbuf_from_stdio (JCF *jcf, int count) -{ - FILE *file = (FILE*) (jcf->read_state); - if (count > jcf->buffer_end - jcf->read_ptr) - { - JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer; - 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); - jcf->buffer = new_buffer; - jcf->buffer_end = new_buffer + new_size; - jcf->read_ptr = new_buffer + old_read_ptr; - jcf->read_end = new_buffer + old_read_end; - } - count -= jcf->read_end - jcf->read_ptr; - if (count <= 0) - return 0; - if ((int) fread (jcf->read_end, 1, count, file) != count) - jcf_unexpected_eof (jcf, count); - jcf->read_end += count; - return 0; -} - -#include "zipfile.h" - -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. - Return NULL if the .zip file is malformed. -*/ - -ZipFile * -opendir_in_zip (const char *zipfile, int is_system) -{ - struct ZipFile* zipf; - char magic [4]; - int fd; - for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next) - { - if (strcmp (zipf->name, zipfile) == 0) - return zipf; - } - - zipf = ALLOC (sizeof (struct ZipFile) + strlen (zipfile) + 1); - zipf->next = SeenZipFiles; - zipf->name = (char*)(zipf+1); - strcpy (zipf->name, zipfile); - fd = open (zipfile, O_RDONLY | O_BINARY); - zipf->fd = fd; - if (fd < 0) - { - /* A missing zip file is not considered an error. - We may want to re-consider that. FIXME. */ - 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; - lseek (fd, 0L, SEEK_SET); - if (read_zip_archive (zipf) != 0) - return NULL; - } - - SeenZipFiles = zipf; - return zipf; -} - -/* Returns: - 0: OK - zipmember found. - -1: Not found. - -2: Malformed archive. -*/ - -int -open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember, - int is_system) -{ - ZipDirectory *zipd; - int i, len; - ZipFile *zipf = opendir_in_zip (zipfile, is_system); - - if (zipf == NULL) - return -2; - - if (!zipmember) - return 0; - - len = strlen (zipmember); - - zipd = (struct ZipDirectory*) zipf->central_directory; - for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd)) - { - if (len == zipd->filename_length && - strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0) - { - JCF_ZERO (jcf); - - jcf->filename = xstrdup (zipfile); - jcf->classname = xstrdup (zipmember); - return read_zip_member(jcf, zipd, zipf); - } - } - return -1; -} - -/* Read data from zip archive member. */ - -int -read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf) -{ - jcf->filbuf = jcf_unexpected_eof; - jcf->zipd = zipd; - - if (zipd->compression_method == Z_NO_COMPRESSION) - { - 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 - { - 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; -} - -const char * -open_class (const char *filename, JCF *jcf, int fd, const char *dep_name) -{ - if (jcf) - { - struct stat stat_buf; - if (fstat (fd, &stat_buf) != 0 - || ! S_ISREG (stat_buf.st_mode)) - { - perror ("Could not figure length of .class file"); - return NULL; - } - if (dep_name != NULL) - jcf_dependency_add_file (dep_name, 0); - JCF_ZERO (jcf); - 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; - if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size) - { - perror ("Failed to read .class file"); - return NULL; - } - close (fd); - jcf->filbuf = jcf_unexpected_eof; - } - else - close (fd); - return filename; -} - - -const char * -find_classfile (char *filename, JCF *jcf, const char *dep_name) -{ - int fd = open (filename, O_RDONLY | O_BINARY); - if (fd < 0) - return NULL; - return open_class (filename, jcf, fd, dep_name); -} - -#if JCF_USE_SCANDIR - -/* A comparison function (as for qsort) that compares KEY (a char * - giving the basename of a file) with the name stored in ENTRY (a - dirent **). */ - -static int -compare_path (const void *key, const void *entry) -{ - return strcmp ((const char *) key, - (*((const struct dirent **) entry))->d_name); -} - -/* Returns nonzero if ENTRY names a .java or .class file. */ - -static int -java_or_class_file (const struct dirent *entry) -{ - const char *base = lbasename (entry->d_name); - return (fnmatch ("*.java", base, 0) == 0 || - fnmatch ("*.class", base, 0) == 0); -} - -/* Information about the files present in a particular directory. */ -typedef struct memoized_dirlist_entry -{ - /* The name of the directory. */ - const char *dir; - /* The number of .java and .class files present, or -1 if we could - not, for some reason, obtain the list. */ - int num_files; - /* The .java and .class files in the directory, in alphabetical - order. */ - struct dirent **files; -} memoized_dirlist_entry; - -/* A hash function for a memoized_dirlist_entry. */ -static hashval_t -memoized_dirlist_hash (const void *entry) -{ - const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry; - return htab_hash_string (mde->dir); -} - -/* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to - the directory given by KEY (a char *) giving the directory - name. */ - -static int -memoized_dirlist_lookup_eq (const void *entry, const void *key) -{ - return strcmp ((const char *) key, - ((const memoized_dirlist_entry *) entry)->dir) == 0; -} - -/* A hash table mapping directory names to the lists of .java and - .class files in that directory. */ - -static htab_t memoized_dirlists; - -#endif - -/* Like stat, but avoids actually making the stat system call if we - know that it cannot succeed. FILENAME and BUF are as for stat. */ - -static int -caching_stat (char *filename, struct stat *buf) -{ -#if JCF_USE_SCANDIR - char *sep; - char origsep = 0; - char *base; - memoized_dirlist_entry *dent; - void **slot; - struct memoized_dirlist_entry temp; - - /* If the hashtable has not already been created, create it now. */ - if (!memoized_dirlists) - memoized_dirlists = htab_create (37, - memoized_dirlist_hash, - memoized_dirlist_lookup_eq, - NULL); - - /* Get the name of the directory. */ - sep = strrchr (filename, DIR_SEPARATOR); -#ifdef DIR_SEPARATOR_2 - if (! sep) - sep = strrchr (filename, DIR_SEPARATOR_2); -#endif - if (sep) - { - origsep = *sep; - *sep = '\0'; - base = sep + 1; - } - else - base = filename; - - /* Obtain the entry for this directory from the hash table. This - approach is ok since we know that the hash function only looks at - the directory name. */ - temp.dir = filename; - temp.num_files = 0; - temp.files = NULL; - slot = htab_find_slot (memoized_dirlists, &temp, INSERT); - if (!*slot) - { - /* We have not already scanned this directory; scan it now. */ - dent = XNEW (memoized_dirlist_entry); - dent->dir = xstrdup (filename); - /* Unfortunately, scandir is not fully standardized. In - particular, the type of the function pointer passed as the - third argument sometimes takes a "const struct dirent *" - parameter, and sometimes just a "struct dirent *". We cast - to (void *) and use __extension__ so that either way it is - quietly accepted. FIXME: scandir is not in POSIX. */ - dent->num_files = __extension__ scandir (filename, &dent->files, - (void *) java_or_class_file, - alphasort); - *slot = dent; - } - else - dent = *((memoized_dirlist_entry **) slot); - - /* Put the separator back. */ - if (sep) - *sep = origsep; - - /* If the file is not in the list, there is no need to stat it; it - does not exist. */ - if (dent->num_files != -1 - && !bsearch (base, dent->files, dent->num_files, - sizeof (struct dirent *), compare_path)) - return -1; -#endif - - return stat (filename, buf); -} - -/* 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. 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 * -find_class (const char *classname, int classname_length, JCF *jcf, - int source_ok) -{ - int fd; - int i, k, java = -1, class = -1; - struct stat java_buf, 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. */ - buflen = jcf_path_max_len () + classname_length + 10; - buffer = ALLOC (buflen); - memset (buffer, 0, buflen); - - java_buffer = alloca (buflen); - - jcf->java_source = 0; - - for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry)) - { - const char *path_name = jcf_path_name (entry); - if (class != 0) - { - int dir_len; - - strcpy (buffer, path_name); - i = strlen (buffer); - - /* This is right because we know that `.zip' entries will have a - trailing slash. See jcf-path.c. */ - dir_len = i - 1; - - for (k = 0; k < classname_length; k++, i++) - { - char ch = classname[k]; - buffer[i] = ch == '.' ? '/' : ch; - } - strcpy (buffer+i, ".class"); - - if (jcf_path_is_zipfile (entry)) - { - int err_code; - JCF _jcf; - buffer[dir_len] = '\0'; - SOURCE_FRONTEND_DEBUG - (("Trying [...%s]:%s", - &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)], - buffer+dir_len+1)); - if (jcf == NULL) - jcf = &_jcf; - err_code = open_in_zip (jcf, buffer, buffer+dir_len+1, - jcf_path_is_system (entry)); - if (err_code == 0) - { - /* Should we check if .zip is out-of-date wrt .java? */ - buffer[dir_len] = '('; - strcpy (buffer+i, ".class)"); - if (jcf == &_jcf) - JCF_FINISH (jcf); - return buffer; - } - else - continue; - } - class = caching_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] == '.' - ? DIR_SEPARATOR : classname[m]); - strcpy (java_buffer + m + l, ".java"); - java = caching_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) - { - if (flag_newer) - warning (0, "source file for class %qs is newer than its matching class file. Source file %qs used instead", classname, java_buffer); - class = -1; - } - - if (! java) - dep_file = java_buffer; - else - dep_file = buffer; - if (!class) - { - SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n", - classname+classname_length- - (classname_length <= 30 ? - classname_length : 30))); - 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 = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY); - if (fd >= 0) - { - jcf->java_source = 1; - goto found; - } - } - - 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 *) classname; - - return NULL; - found: - 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 = (char *) open_class (buffer, jcf, fd, dep_file); - jcf->classname = xstrdup (classname); - return buffer; -} - -void -jcf_print_char (FILE *stream, int ch) -{ - switch (ch) - { - case '\'': - case '\\': - case '\"': - fprintf (stream, "\\%c", ch); - break; - case '\n': - fprintf (stream, "\\n"); - break; - case '\t': - fprintf (stream, "\\t"); - break; - case '\r': - fprintf (stream, "\\r"); - break; - default: - if (ch >= ' ' && ch < 127) - putc (ch, stream); - else if (ch < 256) - fprintf (stream, "\\%03x", ch); - else - fprintf (stream, "\\u%04x", ch); - } -} - -/* Print UTF8 string at STR of length LENGTH bytes to STREAM. */ - -void -jcf_print_utf8 (FILE *stream, const unsigned char *str, int length) -{ - const unsigned char * limit = str + length; - while (str < limit) - { - int ch = UTF8_GET (str, limit); - if (ch < 0) - { - fprintf (stream, "\\<invalid>"); - return; - } - jcf_print_char (stream, ch); - } -} - -/* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */ - -void -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) - { - int ch = UTF8_GET (str, limit); - if (ch < 0) - { - fprintf (stream, "\\<invalid>"); - return; - } - jcf_print_char (stream, ch == in_char ? out_char : ch); - } -} - -/* 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. - Only checks internal consistency, but does not check that - any classes, fields, or methods are valid.*/ - -int -verify_constant_pool (JCF *jcf) -{ - int i, n; - for (i = 1; i < JPOOL_SIZE (jcf); i++) - { - switch (JPOOL_TAG (jcf, i)) - { - case CONSTANT_NameAndType: - n = JPOOL_USHORT2 (jcf, i); - if (n <= 0 || n >= JPOOL_SIZE(jcf) - || JPOOL_TAG (jcf, n) != CONSTANT_Utf8) - return i; - /* ... fall through ... */ - case CONSTANT_Class: - case CONSTANT_String: - n = JPOOL_USHORT1 (jcf, i); - if (n <= 0 || n >= JPOOL_SIZE(jcf) - || JPOOL_TAG (jcf, n) != CONSTANT_Utf8) - return i; - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - n = JPOOL_USHORT1 (jcf, i); - if (n <= 0 || n >= JPOOL_SIZE(jcf) - || JPOOL_TAG (jcf, n) != CONSTANT_Class) - return i; - n = JPOOL_USHORT2 (jcf, i); - if (n <= 0 || n >= JPOOL_SIZE(jcf) - || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType) - return i; - break; - case CONSTANT_Long: - case CONSTANT_Double: - i++; - break; - case CONSTANT_Float: - case CONSTANT_Integer: - case CONSTANT_Utf8: - case CONSTANT_Unicode: - break; - default: - return i; - } - } - return 0; -} - -void -format_uint (char *buffer, uint64 value, int base) -{ -#define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8) - char buf[WRITE_BUF_SIZE]; - char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */ - int chars_written; - int i; - - /* Now do the actual conversion, placing the result at the *end* of buf. */ - /* Note this code does not pretend to be optimized. */ - do { - int digit = value % base; - static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - *--buf_ptr = digit_chars[digit]; - value /= base; - } while (value != 0); - - chars_written = buf+WRITE_BUF_SIZE - buf_ptr; - for (i = 0; i < chars_written; i++) - buffer[i] = *buf_ptr++; - buffer[i] = 0; -} - -void -format_int (char *buffer, jlong value, int base) -{ - uint64 abs_value; - if (value < 0) - { - abs_value = -(uint64)value; - *buffer++ = '-'; - } - else - abs_value = (uint64) value; - format_uint (buffer, abs_value, base); -} |