📄 jcf-parse.c
字号:
- and then perhaps rename read_class to load_class. FIXME */voidload_class (class_or_name, verbose) tree class_or_name; int verbose;{ tree name; /* class_or_name can be the name of the class we want to load */ if (TREE_CODE (class_or_name) == IDENTIFIER_NODE) name = class_or_name; /* In some cases, it's a dependency that we process earlier that we though */ else if (TREE_CODE (class_or_name) == TREE_LIST) name = TYPE_NAME (TREE_PURPOSE (class_or_name)); /* Or it's a type in the making */ else name = DECL_NAME (TYPE_NAME (class_or_name)); if (read_class (name) == 0 && verbose) { error ("Cannot find file for class %s.", IDENTIFIER_POINTER (name)); if (TREE_CODE (class_or_name) == RECORD_TYPE) TYPE_SIZE (class_or_name) = error_mark_node;#if 0 /* FIXME: what to do here? */ if (!strcmp (classpath, DEFAULT_CLASS_PATH)) fatal ("giving up");#endif return; }}/* Parse a source file when JCF refers to a source file. */static voidjcf_parse_source (){ tree file; java_parser_context_save_global (); java_push_parser_context (); input_filename = current_jcf->filename; file = get_identifier (input_filename); if (!HAS_BEEN_ALREADY_PARSED_P (file)) { if (!(finput = fopen (input_filename, "r"))) fatal ("input file `%s' just disappeared - jcf_parse_source", input_filename); parse_source_file (file); if (fclose (finput)) fatal ("can't close input file `%s' stream - jcf_parse_source", input_filename); } java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file)); java_parser_context_restore_global ();}/* Parse the .class file JCF. */voidjcf_parse (jcf) JCF* jcf;{ int i, code; if (jcf_parse_preamble (jcf) != 0) fatal ("Not a valid Java .class file.\n"); code = jcf_parse_constant_pool (jcf); if (code != 0) fatal ("error while parsing constant pool"); code = verify_constant_pool (jcf); if (code > 0) fatal ("error in constant pool entry #%d\n", code); jcf_parse_class (jcf); if (main_class == NULL_TREE) main_class = current_class; if (! quiet_flag && TYPE_NAME (current_class)) fprintf (stderr, " class %s", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); if (CLASS_LOADED_P (current_class)) return; CLASS_LOADED_P (current_class) = 1; for (i = 1; i < JPOOL_SIZE(jcf); i++) { switch (JPOOL_TAG (jcf, i)) { case CONSTANT_Class: get_class_constant (jcf, i); break; } } code = jcf_parse_fields (jcf); if (code != 0) fatal ("error while parsing fields"); code = jcf_parse_methods (jcf); if (code != 0) fatal ("error while parsing methods"); code = jcf_parse_final_attributes (jcf); if (code != 0) fatal ("error while parsing final attributes"); /* The fields of class_type_node are already in correct order. */ if (current_class != class_type_node && current_class != object_type_node) TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class)); push_obstacks (&permanent_obstack, &permanent_obstack); layout_class (current_class); if (current_class == object_type_node) layout_class_methods (object_type_node); else all_class_list = tree_cons (NULL_TREE, TYPE_NAME (current_class), all_class_list ); pop_obstacks ();}voidinit_outgoing_cpool (){ current_constant_pool_data_ref = NULL_TREE; if (outgoing_cpool == NULL) { static CPool outgoing_cpool_buffer; outgoing_cpool = &outgoing_cpool_buffer; CPOOL_INIT(outgoing_cpool); } else { CPOOL_REINIT(outgoing_cpool); }}static voidparse_class_file (){ tree method; char *save_input_filename = input_filename; int save_lineno = lineno; java_layout_seen_class_methods (); input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class)); lineno = 0; debug_start_source_file (input_filename); init_outgoing_cpool (); for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class)); method != NULL_TREE; method = TREE_CHAIN (method)) { JCF *jcf = current_jcf; if (METHOD_NATIVE (method) || METHOD_ABSTRACT (method)) continue; if (DECL_CODE_OFFSET (method) == 0) { error ("missing Code attribute"); continue; } lineno = 0; if (DECL_LINENUMBERS_OFFSET (method)) { register int i; register unsigned char *ptr; JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method)); linenumber_count = i = JCF_readu2 (jcf); linenumber_table = ptr = jcf->read_ptr; for (ptr += 2; --i >= 0; ptr += 4) { int line = GET_u2 (ptr); /* Set initial lineno lineno to smallest linenumber. * Needs to be set before init_function_start. */ if (lineno == 0 || line < lineno) lineno = line; } } else { linenumber_table = NULL; linenumber_count = 0; } start_java_method (method); give_name_to_locals (jcf); /* Actually generate code. */ expand_byte_code (jcf, method); end_java_method (); } if (flag_emit_class_files) write_classfile (current_class); finish_class (current_class); debug_end_source_file (save_lineno); input_filename = save_input_filename; lineno = save_lineno;}/* Parse a source file, as pointed by the current value of INPUT_FILENAME. */static voidparse_source_file (file) tree file;{ int save_error_count = java_error_count; /* Mark the file as parsed */ HAS_BEEN_ALREADY_PARSED_P (file) = 1; lang_init_source (1); /* Error msgs have no method prototypes */ java_init_lex (); /* Initialize the parser */ java_parse_abort_on_error (); java_parse (); /* Parse and build partial tree nodes. */ java_parse_abort_on_error (); java_complete_class (); /* Parse unsatisfied class decl. */ java_parse_abort_on_error (); java_check_circular_reference (); /* Check on circular references */ java_parse_abort_on_error ();}static intpredefined_filename_p (node) tree node;{ int i; for (i = 0; i < predef_filenames_size; i++) if (predef_filenames [i] == node) return 1; return 0;}intyyparse (){ int several_files = 0; char *list = strdup (input_filename), *next; tree node, current_file_list = NULL_TREE; do { next = strchr (list, '&'); if (next) { *next++ = '\0'; several_files = 1; } if (list[0]) { char *value; tree id; int twice = 0; int len = strlen (list); /* FIXME: this test is only needed until our .java parser is fully capable. */ if (len > 5 && ! strcmp (&list[len - 5], ".java")) saw_java_source = 1; if (*list != '/' && several_files) obstack_grow (&temporary_obstack, "./", 2); obstack_grow0 (&temporary_obstack, list, len); value = obstack_finish (&temporary_obstack); /* Exclude file that we see twice on the command line. For all files except {Class,Error,Object,RuntimeException,String, Throwable}.java we can rely on maybe_get_identifier. For these files, we need to do a linear search of current_file_list. This search happens only for these files, presumably only when we're recompiling libgcj. */ if ((id = maybe_get_identifier (value))) { if (predefined_filename_p (id)) { tree c; for (c = current_file_list; c; c = TREE_CHAIN (c)) if (TREE_VALUE (c) == id) twice = 1; } else twice = 1; } if (twice) { char *saved_input_filename = input_filename; input_filename = value; warning ("source file seen twice on command line and will be " "compiled only once."); input_filename = saved_input_filename; } else { node = get_identifier (value); IS_A_COMMAND_LINE_FILENAME_P (node) = 1; current_file_list = tree_cons (NULL_TREE, node, current_file_list); } } list = next; } while (next); current_jcf = main_jcf; current_file_list = nreverse (current_file_list); for (node = current_file_list; node; node = TREE_CHAIN (node)) { tree name = TREE_VALUE (node); /* Skip already parsed files */ if (HAS_BEEN_ALREADY_PARSED_P (name)) continue; /* Close previous descriptor, if any */ if (main_jcf->read_state && fclose (main_jcf->read_state)) fatal ("failed to close input file `%s' - yyparse", (main_jcf->filename ? main_jcf->filename : "<unknown>")); /* Set jcf up and open a new file */ JCF_ZERO (main_jcf); main_jcf->read_state = fopen (IDENTIFIER_POINTER (name), "rb"); if (main_jcf->read_state == NULL) pfatal_with_name (IDENTIFIER_POINTER (name)); /* Set new input_filename and finput */ finput = main_jcf->read_state;#ifdef IO_BUFFER_SIZE setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);#endif input_filename = IDENTIFIER_POINTER (name); main_jcf->filbuf = jcf_filbuf_from_stdio; switch (jcf_figure_file_type (current_jcf)) { case JCF_ZIP: parse_zip_file_entries (); break; case JCF_CLASS: jcf_parse (current_jcf); parse_class_file (); break; case JCF_SOURCE: java_push_parser_context (); java_parser_context_save_global (); parse_source_file (name); java_parser_context_restore_global (); java_pop_parser_context (1); break; } } java_expand_classes (); if (!java_report_errors () && !flag_syntax_only) emit_register_classes (); return 0;}static struct ZipFileCache *localToFile;/* Process all class entries found in the zip file. */static voidparse_zip_file_entries (void){ struct ZipDirectory *zdir; int i; for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory; i < localToFile->z.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_LANG_SPECIFIC (class)->jcf; current_class = class; if ( !CLASS_LOADED_P (class)) { fseek (current_jcf->read_state, current_jcf->zip_offset, SEEK_SET); jcf_parse (current_jcf); } 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. */ } }}/* Read all the entries of the zip file, creates a class and a JCF. Sets the jcf up for further processing and link it to the created class. */static void process_zip_dir(){ int i; ZipDirectory *zdir; for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory; i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir)) { char *class_name, *file_name, *class_name_in_zip_dir; tree class; JCF *jcf; int j; 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 extention. */ 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; } class_name = ALLOC (zdir->filename_length+1-6); file_name = ALLOC (zdir->filename_length+1); jcf = 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; jcf->filbuf = jcf_filbuf_from_stdio; jcf->seen_in_zip = 1; jcf->java_source = 0; jcf->zip_offset = zdir->filestart; jcf->classname = class_name; jcf->filename = file_name; TYPE_LANG_SPECIFIC (class) = (struct lang_type *) perm_calloc (1, sizeof (struct lang_type)); TYPE_LANG_SPECIFIC (class)->jcf = jcf; }}/* Lookup class NAME and figure whether is a class already found in the current zip file. */static intDEFUN(find_in_current_zip, (name, length, jcf), char *name AND JCF **jcf){ JCF *local_jcf; tree class_name = maybe_get_identifier (name), class, icv; if (!class_name) return 0; if (!(icv = IDENTIFIER_CLASS_VALUE (class_name))) return 0; class = TREE_TYPE (icv); /* Doesn't have jcf specific info ? It's not ours */ if (!TYPE_LANG_SPECIFIC (class) || !TYPE_LANG_SPECIFIC (class)->jcf) return 0; *jcf = local_jcf = TYPE_LANG_SPECIFIC (class)->jcf; fseek (local_jcf->read_state, local_jcf->zip_offset, SEEK_SET); return 1;}/* Figure what kind of file we're dealing with */static intDEFUN(jcf_figure_file_type, (jcf), JCF *jcf){ unsigned char magic_string[4]; uint32 magic; if (fread (magic_string, 1, 4, jcf->read_state) != 4) jcf_unexpected_eof (jcf, 4); fseek (jcf->read_state, 0L, SEEK_SET); magic = GET_u4 (magic_string); if (magic == 0xcafebabe) return JCF_CLASS; /* FIXME: is it a system file? */ if (magic == (JCF_u4)ZIPMAGIC && !open_in_zip (jcf, input_filename, NULL, 0)) { localToFile = ALLOC (sizeof (struct ZipFileCache)); bcopy ((PTR) SeenZipFiles, (PTR) localToFile, sizeof (struct ZipFileCache)); process_zip_dir (); /* Register all the class defined there */ return JCF_ZIP; } return JCF_SOURCE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -