diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 346dd6bea47..bdb9917d6cb 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,26 @@ +2003-01-22 Tom Tromey + + * gcj.texi (Input and output files): Mention non-class entries. + * decl.c (java_init_decl_processing): Call + init_resource_processing. + * java-tree.h (compile_resource_data, write_resource_constructor, + compile_resource_file, init_resource_processing): Declare. + * config-lang.in (gtfiles): Added resource.c. + * Make-lang.in (gt-java-resource.h): New target. + (JAVA_OBJS): Added resource.o. + (java/resource.o): New target. + * resource.c: New file. + * class.c (compile_resource_file): Moved to resource.c. + (registerResource_libfunc): Likewise. + (utf8_decl_list): Mark with GTY; now static. + * jcf-parse.c (classify_zip_file): New function. + (parse_zip_file_entries): Use it; compile .properties files. + (process_zip_dir): Use classify_zip_file and compute_class_name. + Don't write class name into zip directory. + (java_parse_file): Call write_resource_constructor. + (compute_class_name): New function. + * jcf-io.c (read_zip_member): Reindented. + 2003-01-21 Tom Tromey * class.c (supers_all_compiled): New function. diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index 59c8d0eb18b..fc930232051 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -102,13 +102,13 @@ $(srcdir)/java/keyword.h: $(srcdir)/java/keyword.gperf gt-java-class.h gt-java-constants.h gt-java-decl.h : s-gtype ; @true gt-java-expr.h gt-java-jcf-parse.h gt-java-jcf-write.h : s-gtype ; @true gt-java-lang.h gt-java-mangle.h gt-java-parse.h : s-gtype ; @true -gt-java-builtins.h gtype-java.h : s-gtype ; @true +gt-java-builtins.h gtype-java.h gt-java-resource.h : s-gtype ; @true # Executables built by this Makefile: JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \ java/constants.o java/lang.o java/typeck.o java/except.o java/verify.o \ java/zextract.o java/jcf-io.o java/jcf-parse.o java/mangle.o \ - java/mangle_name.o java/builtins.o \ + java/mangle_name.o java/builtins.o java/resource.o \ java/jcf-write.o java/buffer.o java/check-init.o java/jcf-depend.o \ java/jcf-path.o java/xref.o java/boehm.o java/java-tree-inline.o mkdeps.o @@ -324,6 +324,9 @@ java/mangle_name.o: java/mangle_name.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) \ $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(GGC_H) java/parse-scan.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \ $(JAVA_LEX_C) java/parse.h java/lex.h +java/resource.o: java/resource.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ + $(JAVA_TREE_H) $(RTL_H) java/jcf.h java/parse.h toplev.h output.h $(GGC_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/verify.o: java/verify.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \ diff --git a/gcc/java/class.c b/gcc/java/class.c index 1e0e83a7520..d0953cce4ed 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -61,7 +61,6 @@ static int assume_compiled (const char *); static tree build_method_symbols_entry (tree); static GTY(()) rtx registerClass_libfunc; -static GTY(()) rtx registerResource_libfunc; struct obstack temporary_obstack; @@ -742,111 +741,7 @@ hashUtf8String (const char *str, int len) return hash; } -/* Generate a byte array representing the contents of FILENAME. The - array is assigned a unique local symbol. The array represents a - compiled Java resource, which is accessed by the runtime using - NAME. */ -void -compile_resource_file (char *name, const char *filename) -{ - struct stat stat_buf; - int fd; - char *buffer; - char buf[60]; - tree rtype, field = NULL_TREE, data_type, rinit, data, decl; - static int Jr_count = 0; - - fd = open (filename, O_RDONLY | O_BINARY); - if (fd < 0) - { - perror ("Failed to read resource file"); - return; - } - if (fstat (fd, &stat_buf) != 0 - || ! S_ISREG (stat_buf.st_mode)) - { - perror ("Could not figure length of resource file"); - return; - } - buffer = xmalloc (strlen (name) + stat_buf.st_size); - strcpy (buffer, name); - read (fd, buffer + strlen (name), stat_buf.st_size); - close (fd); - data_type = build_prim_array_type (unsigned_byte_type_node, - strlen (name) + stat_buf.st_size); - rtype = make_node (RECORD_TYPE); - PUSH_FIELD (rtype, field, "name_length", unsigned_int_type_node); - PUSH_FIELD (rtype, field, "resource_length", unsigned_int_type_node); - PUSH_FIELD (rtype, field, "data", data_type); - FINISH_RECORD (rtype); - START_RECORD_CONSTRUCTOR (rinit, rtype); - PUSH_FIELD_VALUE (rinit, "name_length", - build_int_2 (strlen (name), 0)); - PUSH_FIELD_VALUE (rinit, "resource_length", - build_int_2 (stat_buf.st_size, 0)); - data = build_string (strlen(name) + stat_buf.st_size, buffer); - TREE_TYPE (data) = data_type; - PUSH_FIELD_VALUE (rinit, "data", data); - FINISH_RECORD_CONSTRUCTOR (rinit); - TREE_CONSTANT (rinit) = 1; - - /* Generate a unique-enough identifier. */ - sprintf(buf, "_Jr%d", ++Jr_count); - - decl = build_decl (VAR_DECL, get_identifier (buf), rtype); - TREE_STATIC (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; - TREE_READONLY (decl) = 1; - TREE_THIS_VOLATILE (decl) = 0; - DECL_INITIAL (decl) = rinit; - layout_decl (decl, 0); - pushdecl (decl); - rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0); - make_decl_rtl (decl, (char*) 0); - assemble_variable (decl, 1, 0, 0); - - { - tree init_name = get_file_function_name ('I'); - tree init_type = build_function_type (void_type_node, end_params_node); - tree init_decl; - - init_decl = build_decl (FUNCTION_DECL, init_name, init_type); - SET_DECL_ASSEMBLER_NAME (init_decl, init_name); - TREE_STATIC (init_decl) = 1; - current_function_decl = init_decl; - DECL_RESULT (init_decl) = build_decl (RESULT_DECL, - NULL_TREE, void_type_node); - - /* It can be a static function as long as collect2 does not have - to scan the object file to find its ctor/dtor routine. */ - TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors; - - pushlevel (0); - make_decl_rtl (init_decl, NULL); - init_function_start (init_decl, input_filename, 0); - expand_function_start (init_decl, 0); - - emit_library_call (registerResource_libfunc, 0, VOIDmode, 1, - gen_rtx (SYMBOL_REF, Pmode, buf), - Pmode); - - expand_function_end (input_filename, 0, 0); - poplevel (1, 0, 1); - { - /* Force generation, even with -O3 or deeper. Gross hack. FIXME */ - int saved_flag = flag_inline_functions; - flag_inline_functions = 0; - rest_of_compilation (init_decl); - flag_inline_functions = saved_flag; - } - current_function_decl = NULL_TREE; - (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0), - DEFAULT_INIT_PRIORITY); - } -} - -tree utf8_decl_list = NULL_TREE; +static GTY(()) tree utf8_decl_list = NULL_TREE; tree build_utf8_ref (tree name) @@ -2209,8 +2104,6 @@ void init_class_processing (void) { registerClass_libfunc = gen_rtx_SYMBOL_REF (Pmode, "_Jv_RegisterClass"); - registerResource_libfunc = - gen_rtx_SYMBOL_REF (Pmode, "_Jv_RegisterResource"); fields_ident = get_identifier ("fields"); info_ident = get_identifier ("info"); gcc_obstack_init (&temporary_obstack); diff --git a/gcc/java/config-lang.in b/gcc/java/config-lang.in index 05a6fdff7e7..41c5f915a71 100644 --- a/gcc/java/config-lang.in +++ b/gcc/java/config-lang.in @@ -36,7 +36,7 @@ compilers="jc1\$(exeext) jvgenmain\$(exeext)" stagestuff="jc1\$(exeext) gcj\$(exeext) jvgenmain\$(exeext) gcjh\$(exeext) jv-scan\$(exeext) jcf-dump\$(exeext)" -gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/jcf.h \$(srcdir)/java/lex.h \$(srcdir)/java/parse.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y" +gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/jcf.h \$(srcdir)/java/lex.h \$(srcdir)/java/parse.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y \$(srcdir)/java/resource.c" target_libs=${libgcj_saved} lang_dirs="zlib fastjar" diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 99c2652160e..218d4baae92 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -397,6 +397,7 @@ java_init_decl_processing (void) tree t; init_class_processing (); + init_resource_processing (); current_function_decl = NULL; current_binding_level = NULL_BINDING_LEVEL; diff --git a/gcc/java/except.c b/gcc/java/except.c index 9ad41a658ba..dcfefb7df23 100644 --- a/gcc/java/except.c +++ b/gcc/java/except.c @@ -324,10 +324,35 @@ prepare_eh_table_type (tree type) else if (is_compiled_class (type)) exp = build_class_ref (type); else - exp = fold (build - (PLUS_EXPR, ptr_type_node, - build_utf8_ref (DECL_NAME (TYPE_NAME (type))), - size_one_node)); + { + tree ctype = make_node (RECORD_TYPE); + tree field = NULL_TREE; + tree cinit, decl; + tree utf8_ref = build_utf8_ref (DECL_NAME (TYPE_NAME (type))); + char buf[64]; + sprintf (buf, "%s_ref", + IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref, 0)))); + PUSH_FIELD (ctype, field, "dummy", ptr_type_node); + PUSH_FIELD (ctype, field, "utf8", utf8const_ptr_type); + FINISH_RECORD (ctype); + START_RECORD_CONSTRUCTOR (cinit, ctype); + PUSH_FIELD_VALUE (cinit, "dummy", integer_minus_one_node); + PUSH_FIELD_VALUE (cinit, "utf8", utf8_ref); + FINISH_RECORD_CONSTRUCTOR (cinit); + TREE_CONSTANT (cinit) = 1; + decl = build_decl (VAR_DECL, get_identifier (buf), utf8const_type); + TREE_STATIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_THIS_VOLATILE (decl) = 0; + DECL_INITIAL (decl) = cinit; + layout_decl (decl, 0); + pushdecl (decl); + rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0); + make_decl_rtl (decl, (char*) 0); + exp = build1 (ADDR_EXPR, utf8const_ptr_type, decl); + } return exp; } diff --git a/gcc/java/gcj.texi b/gcc/java/gcj.texi index 8a40b7739f0..f9518d7bd64 100644 --- a/gcc/java/gcj.texi +++ b/gcc/java/gcj.texi @@ -182,7 +182,10 @@ Java bytecode files. @item @var{file}.zip @itemx @var{file}.jar An archive containing one or more @code{.class} files, all of -which are compiled. The archive may be compressed. +which are compiled. The archive may be compressed. Files in +an archive which don't end with @samp{.class} are treated as +resource files; they are copmiled into the resulting object file +as @samp{core:} URLs. @item @@@var{file} A file containing a whitespace-separated list of input file names. (Currently, these must all be @code{.java} source files, but that diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 88e6f07622b..ccedb9a2e6d 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1299,6 +1299,13 @@ struct rtx_def * java_expand_expr (tree, rtx, enum machine_mode, int); extern void java_inlining_merge_static_initializers (tree, void *); extern void java_inlining_map_static_initializers (tree, void *); +extern void compile_resource_data PARAMS ((char *name, const char *buffer, + int length)); +extern void write_resource_constructor PARAMS ((void)); +extern void compile_resource_file PARAMS ((char *name, const char *filename)); +extern void init_resource_processing PARAMS ((void)); + + #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL) /* Access flags etc for a method (a FUNCTION_DECL): */ diff --git a/gcc/java/jcf-io.c b/gcc/java/jcf-io.c index abc20736b7d..5d6ef25d8ba 100644 --- a/gcc/java/jcf-io.c +++ b/gcc/java/jcf-io.c @@ -186,48 +186,48 @@ open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember, int read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf) { - jcf->filbuf = jcf_unexpected_eof; - jcf->zipd = (void *)zipd; + jcf->filbuf = jcf_unexpected_eof; + jcf->zipd = (void *)zipd; - if (zipd->compression_method == Z_NO_COMPRESSION) - { - jcf->buffer = ALLOC (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; + if (zipd->compression_method == Z_NO_COMPRESSION) + { + jcf->buffer = ALLOC (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 = ALLOC (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 = ALLOC (zipd->size); - d_stream.next_in = 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); - } + jcf->buffer = ALLOC (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 = ALLOC (zipd->size); + d_stream.next_in = 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; + return 0; } const char * diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index 892e5616b5f..a29da453a8b 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -94,6 +94,8 @@ static struct ZipFile *localToFile; /* Declarations of some functions used here. */ static void handle_innerclass_attribute (int count, JCF *); static tree give_name_to_class (JCF *jcf, int index); +static char *compute_class_name (struct ZipDirectory *zdir); +static int classify_zip_file (struct ZipDirectory *zdir); static void parse_zip_file_entries (void); static void process_zip_dir (FILE *); static void parse_source_file_1 (tree, FILE *); @@ -1012,7 +1014,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) finput = fopen (IDENTIFIER_POINTER (name), "rb"); if (finput == NULL) fatal_io_error ("can't open %s", IDENTIFIER_POINTER (name)); - + #ifdef IO_BUFFER_SIZE setvbuf (finput, xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE); @@ -1047,7 +1049,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) if (open_in_zip (main_jcf, input_filename, NULL, 0) < 0) fatal_error ("bad zip/jar file %s", IDENTIFIER_POINTER (name)); localToFile = SeenZipFiles; - /* Register all the class defined there. */ + /* Register all the classes defined there. */ process_zip_dir (main_jcf->read_state); parse_zip_file_entries (); /* @@ -1100,6 +1102,51 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) if (flag_indirect_dispatch) emit_offset_symbol_table (); } + + write_resource_constructor (); +} + +/* Return the name of the class corresponding to the name of the file + in this zip entry. The result is newly allocated using ALLOC. */ +static char * +compute_class_name (struct ZipDirectory *zdir) +{ + char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir); + char *class_name; + int j; + + class_name = ALLOC (zdir->filename_length + 1 - 6); + strncpy (class_name, class_name_in_zip_dir, zdir->filename_length - 6); + class_name [zdir->filename_length - 6] = '\0'; + for (j = 0; class_name[j]; ++j) + class_name[j] = class_name[j] == '/' ? '.' : class_name[j]; + return class_name; +} + +/* Return 0 if we should skip this entry, 1 if it is a .class file, 2 + if it is a property file of some sort. */ +static int +classify_zip_file (struct ZipDirectory *zdir) +{ + char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir); + + if (zdir->filename_length > 6 + && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6], + ".class", 6)) + return 1; + + /* For now we drop the manifest and other information. Maybe it + would make more sense to compile it in? */ + if (zdir->filename_length > 8 + && !strncmp (class_name_in_zip_dir, "META-INF/", 9)) + return 0; + + /* Drop directory entries. */ + if (zdir->filename_length > 0 + && class_name_in_zip_dir[zdir->filename_length - 1] == '/') + return 0; + + return 2; } /* Process all class entries found in the zip file. */ @@ -1113,35 +1160,80 @@ parse_zip_file_entries (void) i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir)) { tree class; - - /* We don't need to consider those files. */ - if (!zdir->size || !zdir->filename_offset) - continue; - class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir))); - current_jcf = TYPE_JCF (class); - current_class = class; - - if ( !CLASS_LOADED_P (class)) + switch (classify_zip_file (zdir)) { - if (! CLASS_PARSED_P (class)) - { - read_zip_member(current_jcf, zdir, localToFile); - jcf_parse (current_jcf); - } - layout_class (current_class); - load_inner_classes (current_class); - } + case 0: + continue; - if (TYPE_SIZE (current_class) != error_mark_node) - { - input_filename = current_jcf->filename; - parse_class_file (); - FREE (current_jcf->buffer); /* No longer necessary */ - /* Note: there is a way to free this buffer right after a - class seen in a zip file has been parsed. The idea is the - set its jcf in such a way that buffer will be reallocated - the time the code for the class will be generated. FIXME. */ + case 1: + { + char *class_name = compute_class_name (zdir); + class = lookup_class (get_identifier (class_name)); + FREE (class_name); + current_jcf = TYPE_JCF (class); + current_class = class; + + if (! CLASS_LOADED_P (class)) + { + if (! CLASS_PARSED_P (class)) + { + read_zip_member (current_jcf, zdir, localToFile); + jcf_parse (current_jcf); + } + layout_class (current_class); + load_inner_classes (current_class); + } + + if (TYPE_SIZE (current_class) != error_mark_node) + { + input_filename = current_jcf->filename; + parse_class_file (); + FREE (current_jcf->buffer); /* No longer necessary */ + /* Note: there is a way to free this buffer right after a + class seen in a zip file has been parsed. The idea is the + set its jcf in such a way that buffer will be reallocated + the time the code for the class will be generated. FIXME. */ + } + } + break; + + case 2: + { + char *file_name, *class_name_in_zip_dir, *buffer; + JCF *jcf; + file_name = ALLOC (zdir->filename_length + 1); + class_name_in_zip_dir = ZIPDIR_FILENAME (zdir); + strncpy (file_name, class_name_in_zip_dir, zdir->filename_length); + file_name[zdir->filename_length] = '\0'; + jcf = ALLOC (sizeof (JCF)); + JCF_ZERO (jcf); + jcf->read_state = finput; + jcf->filbuf = jcf_filbuf_from_stdio; + jcf->java_source = 0; + jcf->classname = NULL; + jcf->filename = file_name; + jcf->zipd = zdir; + + if (read_zip_member (jcf, zdir, localToFile) < 0) + fatal_error ("error while reading %s from zip file", file_name); + + buffer = ALLOC (zdir->filename_length + 1 + + (jcf->buffer_end - jcf->buffer)); + strcpy (buffer, file_name); + memcpy (buffer + zdir->filename_length + 1, + jcf->buffer, jcf->buffer_end - jcf->buffer); + + compile_resource_data (file_name, buffer, + jcf->buffer_end - jcf->buffer); + JCF_FINISH (jcf); + FREE (jcf); + FREE (buffer); + } + break; + + default: + abort (); } } } @@ -1165,33 +1257,18 @@ process_zip_dir (FILE *finput) class_name_in_zip_dir = ZIPDIR_FILENAME (zdir); - /* We choose to not to process entries with a zero size or entries - not bearing the .class extension. */ - if (!zdir->size || !zdir->filename_offset || - strncmp (&class_name_in_zip_dir[zdir->filename_length-6], - ".class", 6)) - { - /* So it will be skipped in parse_zip_file_entries */ - zdir->size = 0; - continue; - } + /* Here we skip non-class files; we handle them later. */ + if (classify_zip_file (zdir) != 1) + continue; - class_name = ALLOC (zdir->filename_length+1-6); + class_name = compute_class_name (zdir); file_name = ALLOC (zdir->filename_length+1); jcf = ggc_alloc (sizeof (JCF)); JCF_ZERO (jcf); - strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6); - class_name [zdir->filename_length-6] = '\0'; strncpy (file_name, class_name_in_zip_dir, zdir->filename_length); file_name [zdir->filename_length] = '\0'; - for (j=0; class_name[j]; j++) - class_name [j] = (class_name [j] == '/' ? '.' : class_name [j]); - - /* Yes, we write back the true class name into the zip directory. */ - strcpy (class_name_in_zip_dir, class_name); - zdir->filename_length = j; class = lookup_class (get_identifier (class_name)); jcf->read_state = finput; diff --git a/gcc/java/resource.c b/gcc/java/resource.c new file mode 100644 index 00000000000..3362cc89322 --- /dev/null +++ b/gcc/java/resource.c @@ -0,0 +1,199 @@ +/* Functions related to building resource files. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 + 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, 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. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "rtl.h" +#include "flags.h" +#include "java-tree.h" +#include "jcf.h" +#include "obstack.h" +#include "toplev.h" +#include "output.h" +#include "parse.h" +#include "function.h" +#include "ggc.h" +#include "stdio.h" +#include "target.h" + +/* DOS brain-damage */ +#ifndef O_BINARY +#define O_BINARY 0 /* MS-DOS brain-damage */ +#endif + +/* A list of all the resources files. */ +static GTY(()) tree resources = NULL; + +/* Function used to register resources. */ +static GTY(()) rtx registerResource_libfunc; + +/* Count of all the resources compiled in this invocation. */ +static int Jr_count = 0; + +void +compile_resource_data (name, buffer, length) + char *name; + const char *buffer; + int length; +{ + tree rtype, field = NULL_TREE, data_type, rinit, data, decl; + char buf[60]; + + data_type = build_prim_array_type (unsigned_byte_type_node, + strlen (name) + length); + rtype = make_node (RECORD_TYPE); + PUSH_FIELD (rtype, field, "name_length", unsigned_int_type_node); + PUSH_FIELD (rtype, field, "resource_length", unsigned_int_type_node); + PUSH_FIELD (rtype, field, "data", data_type); + FINISH_RECORD (rtype); + START_RECORD_CONSTRUCTOR (rinit, rtype); + PUSH_FIELD_VALUE (rinit, "name_length", + build_int_2 (strlen (name), 0)); + PUSH_FIELD_VALUE (rinit, "resource_length", + build_int_2 (length, 0)); + data = build_string (strlen(name) + length, buffer); + TREE_TYPE (data) = data_type; + PUSH_FIELD_VALUE (rinit, "data", data); + FINISH_RECORD_CONSTRUCTOR (rinit); + TREE_CONSTANT (rinit) = 1; + + /* Generate a unique-enough identifier. */ + sprintf (buf, "_Jr%d", ++Jr_count); + + decl = build_decl (VAR_DECL, get_identifier (buf), rtype); + TREE_STATIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_THIS_VOLATILE (decl) = 0; + DECL_INITIAL (decl) = rinit; + layout_decl (decl, 0); + pushdecl (decl); + rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0); + make_decl_rtl (decl, (char*) 0); + assemble_variable (decl, 1, 0, 0); + + resources = tree_cons (NULL_TREE, decl, resources); +} + +void +write_resource_constructor () +{ + tree init_name, init_type, init_decl; + tree iter; + + /* Only do work if required. */ + if (resources == NULL_TREE) + return; + + init_name = get_file_function_name ('I'); + init_type = build_function_type (void_type_node, end_params_node); + + init_decl = build_decl (FUNCTION_DECL, init_name, init_type); + SET_DECL_ASSEMBLER_NAME (init_decl, init_name); + TREE_STATIC (init_decl) = 1; + current_function_decl = init_decl; + DECL_RESULT (init_decl) = build_decl (RESULT_DECL, + NULL_TREE, void_type_node); + + /* It can be a static function as long as collect2 does not have + to scan the object file to find its ctor/dtor routine. */ + TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors; + + pushlevel (0); + make_decl_rtl (init_decl, NULL); + init_function_start (init_decl, input_filename, 0); + expand_function_start (init_decl, 0); + + /* Write out entries in the same order in which they were defined. */ + for (iter = nreverse (resources); iter != NULL_TREE; + iter = TREE_CHAIN (iter)) + { + char *name = IDENTIFIER_POINTER (DECL_NAME (TREE_VALUE (iter))); + emit_library_call (registerResource_libfunc, 0, VOIDmode, 1, + gen_rtx (SYMBOL_REF, Pmode, name), + Pmode); + } + + expand_function_end (input_filename, 0, 0); + poplevel (1, 0, 1); + { + /* Force generation, even with -O3 or deeper. Gross hack. + FIXME. */ + int saved_flag = flag_inline_functions; + flag_inline_functions = 0; + rest_of_compilation (init_decl); + flag_inline_functions = saved_flag; + } + current_function_decl = NULL_TREE; + (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0), + DEFAULT_INIT_PRIORITY); +} + +/* Generate a byte array representing the contents of FILENAME. The + array is assigned a unique local symbol. The array represents a + compiled Java resource, which is accessed by the runtime using + NAME. */ +void +compile_resource_file (name, filename) + char *name; + const char *filename; +{ + struct stat stat_buf; + int fd; + char *buffer; + + fd = open (filename, O_RDONLY | O_BINARY); + if (fd < 0) + { + perror ("Failed to read resource file"); + return; + } + if (fstat (fd, &stat_buf) != 0 + || ! S_ISREG (stat_buf.st_mode)) + { + perror ("Could not figure length of resource file"); + return; + } + buffer = xmalloc (strlen (name) + stat_buf.st_size); + strcpy (buffer, name); + read (fd, buffer + strlen (name), stat_buf.st_size); + close (fd); + + compile_resource_data (name, buffer, stat_buf.st_size); + write_resource_constructor (); +} + +void +init_resource_processing () +{ + registerResource_libfunc = + gen_rtx_SYMBOL_REF (Pmode, "_Jv_RegisterResource"); +} + +#include "gt-java-resource.h"