2003-03-16 Mohan Embar <gnustuff@thisiscool.com>
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Apr 2003 18:24:42 +0000 (18:24 +0000)
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Apr 2003 18:24:42 +0000 (18:24 +0000)
        * Make-lang.in: added win32-host.c
        * jcf.h: defined macro JCF_OPEN_EXACT_CASE which
        resolves to open() on non-Win32 platforms and
        Win32-specific jcf_open_exact_case() on Win32
        * jcf-io.c (find_class): use JCF_OPEN_EXACT_CASE
        when trying .java and .class files
        * win32-host.c: added to repository. Defines
        Win32-specific jcf_open_exact_case()

2003-04-10  Andrew Haley  <aph@redhat.com>

        * jcf-write.c (struct jcf_partial): num_jsrs: new field.
        (maybe_free_localvar): Renamed from localvar_free.
        Add new arg, really.
        (generate_bytecode_insns): Set new variable, jsrs.
        Only free local vars if no jsr insns have been emittted.
        Call maybe_free_localvar, not localvar_free.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65430 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/java/ChangeLog
gcc/java/Make-lang.in
gcc/java/jcf-io.c
gcc/java/jcf-write.c
gcc/java/jcf.h
gcc/java/win32-host.c [new file with mode: 0644]

index c141615..85a30a9 100644 (file)
@@ -1,3 +1,23 @@
+2003-03-16  Mohan Embar  <gnustuff@thisiscool.com>
+
+       * Make-lang.in: added win32-host.c
+       * jcf.h: defined macro JCF_OPEN_EXACT_CASE which
+       resolves to open() on non-Win32 platforms and
+       Win32-specific jcf_open_exact_case() on Win32
+       * jcf-io.c (find_class): use JCF_OPEN_EXACT_CASE
+       when trying .java and .class files
+       * win32-host.c: added to repository. Defines
+       Win32-specific jcf_open_exact_case()
+
+2003-04-10  Andrew Haley  <aph@redhat.com>
+
+       * jcf-write.c (struct jcf_partial): num_jsrs: new field.
+       (maybe_free_localvar): Renamed from localvar_free.
+       Add new arg, really.
+       (generate_bytecode_insns): Set new variable, jsrs.
+       Only free local vars if no jsr insns have been emittted.
+       Call maybe_free_localvar, not localvar_free.
+
 2003-03-30  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * gcj.texi: Remove @ at start of file.
index 9a97da5..5d74714 100644 (file)
@@ -334,6 +334,7 @@ java/resource.o: java/resource.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   $(TARGET_H) function.h gt-java-resource.h
 java/typeck.o: java/typeck.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
   java/convert.h toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) real.h
+java/win32-host.o: java/win32-host.c $(CONFIG_H) $(SYSTEM_H) java/jcf.h
 java/verify.o: java/verify.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
   java/javaop.h java/java-opcodes.h java/java-except.h toplev.h $(SYSTEM_H) \
   coretypes.h $(TM_H)
index c280f1f..d673ec8 100644 (file)
@@ -544,7 +544,7 @@ find_class (const char *classname, int classname_length, JCF *jcf,
                              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;
     }
@@ -556,7 +556,7 @@ find_class (const char *classname, int classname_length, JCF *jcf,
                              classname+classname_length-
                              (classname_length <= 30 ? 
                               classname_length : 30)));
-      fd = open (buffer, O_RDONLY);
+      fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY);
       if (fd >= 0)
        {
          jcf->java_source = 1;
index d9fc650..9c05a5a 100644 (file)
@@ -279,6 +279,9 @@ struct jcf_partial
 
   /* Information about the current switch statement. */
   struct jcf_switch_state *sw_state;
+
+  /* The count of jsr instructions that have been emmitted.  */
+  long num_jsrs;
 };
 
 static void generate_bytecode_insns (tree, int, struct jcf_partial *);
@@ -293,7 +296,7 @@ static void define_jcf_label (struct jcf_block *, struct jcf_partial *);
 static struct jcf_block * get_jcf_label_here (struct jcf_partial *);
 static void put_linenumber (int, struct jcf_partial *);
 static void localvar_alloc (tree, struct jcf_partial *);
-static void localvar_free (tree, struct jcf_partial *);
+static void maybe_free_localvar (tree, struct jcf_partial *, int);
 static int get_access_flags (tree);
 static void write_chunks (FILE *, struct chunk *);
 static int adjust_typed_op (tree, int);
@@ -601,7 +604,7 @@ localvar_alloc (tree decl, struct jcf_partial *state)
 }
 
 static void
-localvar_free (tree decl, struct jcf_partial *state)
+maybe_free_localvar (tree decl, struct jcf_partial *state, int really)
 {
   struct jcf_block *end_label = get_jcf_label_here (state);
   int index = DECL_LOCAL_INDEX (decl);
@@ -613,6 +616,8 @@ localvar_free (tree decl, struct jcf_partial *state)
 
   if (info->decl != decl)
     abort ();
+  if (! really)
+    return;
   ptr[0] = NULL;
   if (wide)
     {
@@ -1066,6 +1071,7 @@ emit_jsr (struct jcf_block *target, struct jcf_partial *state)
   OP1 (OPCODE_jsr);
   /* Value is 1 byte from reloc back to start of instruction.  */
   emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
+  state->num_jsrs++;
 }
 
 /* Generate code to evaluate EXP.  If the result is true,
@@ -1347,7 +1353,7 @@ generate_bytecode_return (tree exp, struct jcf_partial *state)
          emit_store (state->return_value_decl, state);
          call_cleanups (NULL, state);
          emit_load (state->return_value_decl, state);
-         /* If we call localvar_free (state->return_value_decl, state),
+         /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
             then we risk the save decl erroneously re-used in the
             finalizer.  Instead, we keep the state->return_value_decl
             allocated through the rest of the method.  This is not
@@ -1384,6 +1390,7 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
        {
          tree local;
          tree body = BLOCK_EXPR_BODY (exp);
+         long jsrs = state->num_jsrs;
          for (local = BLOCK_EXPR_DECLS (exp); local; )
            {
              tree next = TREE_CHAIN (local);
@@ -1397,10 +1404,11 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
              body = TREE_OPERAND (body, 1);
            }
          generate_bytecode_insns (body, target, state);
+         
          for (local = BLOCK_EXPR_DECLS (exp); local; )
            {
              tree next = TREE_CHAIN (local);
-             localvar_free (local, state);
+             maybe_free_localvar (local, state, state->num_jsrs <= jsrs);
              local = next;
            }
        }
@@ -2354,8 +2362,8 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
        if (CAN_COMPLETE_NORMALLY (finally))
          {
            maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
-           localvar_free (exception_decl, state);
-           localvar_free (return_link, state);
+           maybe_free_localvar (exception_decl, state, 1);
+           maybe_free_localvar (return_link, state, 1);
            define_jcf_label (finished_label, state);
          }
       }
@@ -2960,6 +2968,7 @@ generate_classfile (tree clas, struct jcf_partial *state)
          get_jcf_label_here (state);  /* Force a first block. */
          for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
            localvar_alloc (t, state);
+         state->num_jsrs = 0;
          generate_bytecode_insns (body, IGNORE_TARGET, state);
          if (CAN_COMPLETE_NORMALLY (body))
            {
@@ -2969,9 +2978,9 @@ generate_classfile (tree clas, struct jcf_partial *state)
              OP1 (OPCODE_return);
            }
          for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
-           localvar_free (t, state);
+           maybe_free_localvar (t, state, 1);
          if (state->return_value_decl != NULL_TREE)
-           localvar_free (state->return_value_decl, state);
+           maybe_free_localvar (state->return_value_decl, state, 1);
          finish_jcf_block (state);
          perform_relocations (state);
 
index 9680974..5a28735 100644 (file)
@@ -63,6 +63,24 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #define COMPARE_FILENAMES(X, Y) strcmp ((X), (Y))
 #endif
 
+/* On case-insensitive file systems, we need to ensure that a request
+   to open a .java or .class file is honored only if the file to be
+   opened is of the exact case we are asking for. In other words, we
+   want to override the inherent case insensitivity of the underlying
+   file system. On other platforms, this macro becomes the vanilla
+   open() call.
+
+   If you want to add another host, add your define to the list below
+   (i.e. defined(WIN32) || defined(YOUR_HOST)) and add an host-specific
+   .c file to Make-lang.in similar to win32-host.c  */
+#if defined(WIN32)
+extern int
+jcf_open_exact_case (const char* filename, int oflag);
+#define JCF_OPEN_EXACT_CASE(X, Y) jcf_open_exact_case (X, Y)
+#else
+#define JCF_OPEN_EXACT_CASE open
+#endif /* WIN32 */
+
 struct JCF;
 typedef int (*jcf_filbuf_t) PARAMS ((struct JCF*, int needed));
 
diff --git a/gcc/java/win32-host.c b/gcc/java/win32-host.c
new file mode 100644 (file)
index 0000000..7ab8fa5
--- /dev/null
@@ -0,0 +1,85 @@
+/* Platform-Specific Win32 Functions
+   Copyright (C) 2003  Free Software Foundation, Inc.
+
+This program 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.
+
+This program 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.
+
+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 Mohan Embar <gnustuff@thisiscool.com>, March 2003. */
+
+#ifdef WIN32
+
+#include "config.h"
+#include "system.h"
+
+#include "jcf.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+/* Simulate an open() failure with ENOENT */
+static int
+file_not_found (void);
+
+static int
+file_not_found (void)
+{
+  errno = ENOENT;
+  return -1;
+}
+
+int
+jcf_open_exact_case (const char *filename, int oflag)
+{
+  int filename_len = strlen (filename);
+  int found_file_len;
+  HANDLE found_file_handle;
+  WIN32_FIND_DATA fd;
+  
+  /* See if we can find this file. */
+  found_file_handle = FindFirstFile (filename, &fd);
+  if (found_file_handle == INVALID_HANDLE_VALUE)
+    return file_not_found ();
+  FindClose (found_file_handle);
+
+  found_file_len = strlen (fd.cFileName);
+  
+  /* This should never happen. */
+  if (found_file_len > filename_len)
+    return file_not_found ();
+  
+  /* Here, we're only actually comparing the filename and not
+     checking the case of any containing directory components.
+     Although we're not fully obeying our contract, checking
+     all directory components would be tedious and time-consuming
+     and it's a pretty safe assumption that mixed-case package
+     names are a fringe case.... */
+  if (strcmp (filename + filename_len - found_file_len, fd.cFileName))
+    {
+      /* Reject this because it is not a perfect-case match. */
+      /* printf("************\nRejected:\n%s\n%s\n************\n\n", filename, fd.cFileName); */
+      return file_not_found ();
+    }
+  else
+    {
+      return open (filename, oflag);
+    }
+}
+
+#endif /* WIN32 */