OSDN Git Service

Uniquization of constants at the Tree level
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-io.c
index 43e96cf..28a48bb 100644 (file)
@@ -1,20 +1,22 @@
 /* Utility routines for finding and reading Java(TM) .class files.
-   Copyright (C) 1996, 1998  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
+<http://www.gnu.org/licenses/>.  
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -24,15 +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 <sys/stat.h>
-#include <sys/wait.h>
+#include "tree.h"
+#include "toplev.h"
+#include "java-tree.h"
+#include "hashtab.h"
+#include <dirent.h>
 
-/* This is true if the user specified a `.java' file on the command
-   line.  Otherwise it is 0.  FIXME: this is temporary, until our
-   .java parser is fully working.  */
-int saw_java_source = 0;
+#include "zlib.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -40,8 +44,7 @@ int saw_java_source = 0;
 #endif
 
 int
-DEFUN(jcf_unexpected_eof, (jcf, count),
-      JCF *jcf AND int count)
+jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
 {
   if (jcf->filename)
     fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
@@ -51,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)
@@ -64,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)
@@ -74,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;
@@ -84,7 +86,7 @@ DEFUN(jcf_filbuf_from_stdio, (jcf, count),
   count -= jcf->read_end - jcf->read_ptr;
   if (count <= 0)
     return 0;
-  if (fread (jcf->read_end, 1, count, file) != count)
+  if ((int) fread (jcf->read_end, 1, count, file) != count)
     jcf_unexpected_eof (jcf, count);
   jcf->read_end += count;
   return 0;
@@ -92,105 +94,150 @@ DEFUN(jcf_filbuf_from_stdio, (jcf, count),
 
 #include "zipfile.h"
 
-struct ZipFileCache *SeenZipFiles = NULL;
+struct ZipFile *SeenZipFiles = NULL;
 
-int
-DEFUN(open_in_zip, (jcf, zipfile, zipmember),
-      JCF *jcf AND const char *zipfile AND const char *zipmember
-      AND int is_system)
+/* 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 ZipFileCache* zipf;
-  ZipDirectory *zipd;
-  int i, len;
-  for (zipf = SeenZipFiles; ; zipf = zipf->next)
+  struct ZipFile* zipf;
+  char magic [4];
+  int fd;
+  for (zipf = SeenZipFiles;  zipf != NULL;  zipf = zipf->next)
     {
-      if (zipf == NULL)
+      if (strcmp (zipf->name, zipfile) == 0)
+       return zipf;
+    }
+
+  zipf = XNEWVAR (struct ZipFile, 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)
        {
-         char magic [4];
-         int fd = open (zipfile, O_RDONLY | O_BINARY);
-         jcf_dependency_add_file (zipfile, is_system);
-         if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
-           return -1;
-         lseek (fd, 0L, SEEK_SET);
-         zipf = ALLOC (sizeof (struct ZipFileCache) + strlen (zipfile) + 1);
-         zipf->next = SeenZipFiles;
-         zipf->name = (char*)(zipf+1);
-         strcpy (zipf->name, zipfile);
-         SeenZipFiles = zipf;
-         zipf->z.fd = fd;
-         if (fd == -1)
-           {
-             /* A missing zip file is not considered an error. */
-             zipf->z.count = 0;
-             zipf->z.dir_size = 0;
-             zipf->z.central_directory = NULL;
-             return -1;
-           }
-         else
-           {
-             if (read_zip_archive (&zipf->z) != 0)
-               return -2; /* This however should be an error - FIXME */
-           }
-         break;
+         free (zipf);
+         close (fd);
+         return NULL;
+       }
+      lseek (fd, 0L, SEEK_SET);
+      if (read_zip_archive (zipf) != 0)
+       {
+         free (zipf);
+         close (fd);
+         return NULL;
        }
-      if (strcmp (zipf->name, zipfile) == 0)
-       break;
     }
 
+  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->z.central_directory;
-  for (i = 0; i < zipf->z.count; i++, zipd = ZIPDIR_NEXT (zipd))
+  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->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 = strdup (zipfile);
-         jcf->classname = strdup (zipmember);
-         jcf->zipd = (void *)zipd;
-         if (lseek (zipf->z.fd, zipd->filestart, 0) < 0
-             || read (zipf->z.fd, jcf->buffer, zipd->size) != zipd->size)
-           return -2;
-         return 0;
+
+         jcf->filename = xstrdup (zipfile);
+         jcf->classname = xstrdup (zipmember);
+         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 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 char *dep_name)
+
+const char *
+open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
 {
   if (jcf)
     {
@@ -204,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");
@@ -222,240 +269,150 @@ DEFUN(open_class, (filename, jcf, fd, dep_name),
     close (fd);
   return filename;
 }
-#endif
 
 
-char *
-DEFUN(find_classfile, (filename, jcf, dep_name),
-      char *filename AND JCF *jcf AND char *dep_name)
+const char *
+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 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.  With
-   DO_CLASS_FILE set to 1, search a .class/.java file named after
-   CLASSNAME, otherwise, search a ZIP directory entry named after
-   CLASSNAME.  */
+/* Returns 1 if the CLASSNAME (really a char *) matches the name
+   stored in TABLE_ENTRY (also a char *).  */
 
-char *
-DEFUN(find_class, (classname, classname_length, jcf, do_class_file),
-      const char *classname AND int classname_length AND JCF *jcf AND int do_class_file)
+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)
 {
-#if JCF_USE_STDIO
-  FILE *stream;
-#else
   int fd;
-#endif
-  int i, k, java, class;
-  struct stat java_buf, class_buf;
+  int i, k, klass = -1;
+  struct stat class_buf;
   char *dep_file;
-  void *entry, *java_entry;
-  char *java_buffer;
+  void *entry;
+  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 = jcf->outofsynch = 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))
     {
-      int dir_len;
+      const char *path_name = jcf_path_name (entry);
+      if (klass != 0)
+       {
+         int dir_len;
 
-      strcpy (buffer, jcf_path_name (entry));
-      i = strlen (buffer);
+         strcpy (buffer, path_name);
+         i = strlen (buffer);
 
-      dir_len = i - 1;
+         /* 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;
-       }
-      if (do_class_file)
-       strcpy (buffer+i, ".class");
+         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;
-         if (!do_class_file)
-           strcpy (buffer+i, "/");
-         buffer[dir_len] = '\0';
-         if (do_class_file)
-           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)
+         if (jcf_path_is_zipfile (entry))
            {
-             if (!do_class_file)
-               jcf->seen_in_zip = 1;
-             else
+             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;
                }
-             if (jcf == &_jcf)
-               JCF_FINISH (jcf);
-             return buffer;
-           }
-         else
-           continue;
-       }
-
-      /* If we do directories, do them here */
-      if (!do_class_file)
-       {
-         struct stat dir_buff;
-         int dir;
-         buffer[i] = '\0';     /* Was previously unterminated here. */
-         if (!(dir = stat (buffer, &dir_buff)))
-           {
-             jcf->seen_in_zip = 0;
-             goto found;
+             else
+               continue;
            }
+         klass = stat (buffer, &class_buf);
        }
+    }
 
-      class = stat (buffer, &class_buf);
-      /* This is a little odd: if we didn't find the class file, we
-        can just skip to the next iteration.  However, if this is the
-        last iteration, then we want to search for the .java file as
-        well.  It was a little easier to implement this with two
-        loops, as opposed to checking for each type of file each time
-        through the loop.  */
-      if (class && jcf_path_next (entry))
-       continue;
-
-      /* Check for out of synch .class/.java files.  */
-      java = 1;
-      for (java_entry = jcf_path_start ();
-          java && java_entry != NULL;
-          java_entry = jcf_path_next (java_entry))
-       {
-         int m, l;
-
-         if (jcf_path_is_zipfile (java_entry))
-           continue;
+  dep_file = buffer;
+  if (!klass)
+    {
+      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;
+    }
 
-         /* Compute name of .java file.  */
-         strcpy (java_buffer, jcf_path_name (java_entry));
-         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");
-
-         /* FIXME: until the `.java' parser is fully working, we only
-            look for a .java file when one was mentioned on the
-            command line.  This lets us test the .java parser fairly
-            easily, without compromising our ability to use the
-            .class parser without fear.  */
-         if (saw_java_source)
-           java = stat (java_buffer, &java_buf);
-       }
+  free (buffer);
 
-      if (! java && ! class && java_buf.st_mtime >= class_buf.st_mtime)
-       jcf->outofsynch = 1;
+  /* 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);
 
-      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)
-       {
-         SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
-         fd = open (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 (("Trying %s", buffer));
-         fd = open (buffer, O_RDONLY);
-         if (fd >= 0)
-           {
-             jcf->java_source = 1;
-             goto found;
-           }
-       }
-#endif
-    }
-  free (buffer);
   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 = (char *) strdup (buffer);
-      close (fd);              /* We use STDIO for source file */
-    }
-  else if (do_class_file)
-    buffer = open_class (buffer, jcf, fd, dep_file);
-  jcf->classname = (char *) ALLOC (classname_length + 1);
-  strncpy (jcf->classname, classname, classname_length + 1);
-  jcf->classname = (char *) strdup (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)
     {
@@ -486,10 +443,9 @@ 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 unsigned char *str AND int length)
+jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
 {
-  unsigned char* limit = str + length;
+  const unsigned char * limit = str + length;
   while (str < limit)
     {
       int ch = UTF8_GET (str, limit);
@@ -505,26 +461,30 @@ 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 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)
 {
-
-  int i;/* FIXME - actually handle Unicode! */
-  for (i = 0; i < length; i++)
+  const unsigned char *limit = str + length;
+  while (str < limit)
     {
-      int ch = str[i];
+      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. */
+   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)