⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jcf-parse.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Parser for Java(TM) .class files.   Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.Java and all Java-based marks are trademarks or registered trademarksof 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> */#include "config.h"#include "system.h"#include "tree.h"#include "obstack.h"#include "flags.h"#include "java-except.h"#include "input.h"#include "java-tree.h"#include "toplev.h"#include "parse.h"/* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */#define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX)#define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX))#define JPOOL_UTF_DATA(JCF, INDEX) \  ((unsigned char*) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX)))#define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \  do { \    unsigned char save;  unsigned char *text; \    JCF_FILL (JCF, (LENGTH)+1); /* Make sure we read 1 byte beyond string. */ \    text = (JCF)->read_ptr; \    save = text[LENGTH]; \    text[LENGTH] = 0; \    (JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \    text[LENGTH] = save; \    JCF_SKIP (JCF, LENGTH); } while (0)#include "jcf.h"extern struct obstack *saveable_obstack;extern struct obstack temporary_obstack;extern struct obstack permanent_obstack;/* 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;/* The class we are currently processing. */tree current_class = NULL_TREE;/* The class we started with. */tree main_class = NULL_TREE;/* List of all class DECL seen so far.  */tree all_class_list = NULL_TREE;/* The FIELD_DECL for the current field.  */static tree current_field = NULL_TREE;/* The METHOD_DECL for the current method.  */static tree current_method = NULL_TREE;/* The Java .class file that provides main_class;  the main input file. */static struct JCF main_jcf[1];/* Declarations of some functions used here.  */static tree give_name_to_class PROTO ((JCF *jcf, int index));static void parse_zip_file_entries PROTO ((void));static void process_zip_dir PROTO ((void));static void parse_source_file PROTO ((tree));static void jcf_parse_source PROTO ((void));static int jcf_figure_file_type PROTO ((JCF *));static int find_in_current_zip PROTO ((char *, struct JCF **));static void parse_class_file PROTO ((void));/* Handle "SourceFile" attribute. */voidset_source_filename (jcf, index)     JCF *jcf;     int index;{  tree sfname_id = get_name_constant (jcf, index);  char *sfname = IDENTIFIER_POINTER (sfname_id);  if (input_filename != NULL)    {      int old_len = strlen (input_filename);      int new_len = IDENTIFIER_LENGTH (sfname_id);      /* Use the current input_filename (derived from the class name)	 if it has a directory prefix, but otherwise matches sfname. */      if (old_len > new_len	  && strcmp (sfname, input_filename + old_len - new_len) == 0	  && (input_filename[old_len - new_len - 1] == '/'	      || input_filename[old_len - new_len - 1] == '\\'))	return;    }  input_filename = sfname;  DECL_SOURCE_FILE (TYPE_NAME (current_class)) = sfname;  if (current_class == main_class) main_input_filename = input_filename;}#define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)#define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \{ tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \  current_class = give_name_to_class (jcf, THIS); \  set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}#define HANDLE_CLASS_INTERFACE(INDEX) \  add_interface (current_class, get_class_constant (jcf, INDEX))#define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \{ int sig_index = SIGNATURE; \  current_field = add_field (current_class, get_name_constant (jcf, NAME), \			     parse_signature (jcf, sig_index), ACCESS_FLAGS); \ set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); }#define HANDLE_END_FIELDS() \  (current_field = NULL_TREE)#define HANDLE_CONSTANTVALUE(INDEX) \{ tree constant;  int index = INDEX; \  if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \    tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \    constant = build_utf8_ref (name); \  } \  else \    constant = get_constant (jcf, index); \  set_constant_value (current_field, constant); }#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \ (current_method = add_method (current_class, ACCESS_FLAGS, \			       get_name_constant (jcf, NAME), \			       get_name_constant (jcf, SIGNATURE)), \  DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \  DECL_LINENUMBERS_OFFSET (current_method) = 0)#define HANDLE_END_METHODS() \{ tree handle_type = CLASS_TO_HANDLE_TYPE (current_class); \  if (handle_type != current_class) layout_type (handle_type); }#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \{ DECL_MAX_STACK (current_method) = (MAX_STACK); \  DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \  DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \  DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }#define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \{ int n = (COUNT); \  DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \  JCF_SKIP (jcf, n * 10); }#define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \{ int n = (COUNT); \  DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \  JCF_SKIP (jcf, n * 4); }#define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \{ \  int n = COUNT; \  tree list = DECL_FUNCTION_THROWS (current_method); \  while (--n >= 0) \    { \      tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \      list = tree_cons (NULL_TREE, thrown_class, list); \    } \  DECL_FUNCTION_THROWS (current_method) = nreverse (list); \}#include "jcf-reader.c"static int yydebug;treeparse_signature (jcf, sig_index)     JCF *jcf;     int sig_index;{  if (sig_index <= 0 || sig_index >= JPOOL_SIZE(jcf)      || JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8)    fatal ("invalid field/method signature");  else    {      return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),				     JPOOL_UTF_LENGTH (jcf, sig_index));    }}voidinit_lex (){  /* Make identifier nodes long enough for the language-specific slots.  */  set_identifier_size (sizeof (struct lang_identifier));}voidset_yydebug (value)     int value;{  yydebug = value;}treeget_constant (jcf, index)  JCF *jcf;  int index;{  tree value;  int tag;  if (index <= 0 || index >= JPOOL_SIZE(jcf))    goto bad;  tag = JPOOL_TAG (jcf, index);  if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)    return (tree) jcf->cpool.data[index];  push_obstacks (&permanent_obstack, &permanent_obstack);  switch (tag)    {    case CONSTANT_Integer:      {	jint num = JPOOL_INT(jcf, index);	value = build_int_2 (num, num < 0 ? -1 : 0);	TREE_TYPE (value) = int_type_node;	break;      }    case CONSTANT_Long:      {	jint num = JPOOL_INT (jcf, index);	HOST_WIDE_INT lo, hi;	lshift_double (num, 0, 32, 64, &lo, &hi, 0);	num = JPOOL_INT (jcf, index+1);	add_double (lo, hi, num, 0, &lo, &hi);	value = build_int_2 (lo, hi);	TREE_TYPE (value) = long_type_node;	force_fit_type (value, 0);	break;      }#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT    case CONSTANT_Float:      {	jint num = JPOOL_INT(jcf, index);	REAL_VALUE_TYPE d;#ifdef REAL_ARITHMETIC	d = REAL_VALUE_FROM_TARGET_SINGLE (num);#else	union { float f;  jint i; } u;	u.i = num;	d = u.f;#endif	value = build_real (float_type_node, d);	break;      }    case CONSTANT_Double:      {	HOST_WIDE_INT num[2];	REAL_VALUE_TYPE d;	HOST_WIDE_INT lo, hi;	num[0] = JPOOL_INT (jcf, index);	lshift_double (num[0], 0, 32, 64, &lo, &hi, 0);	num[0] = JPOOL_INT (jcf, index+1);	add_double (lo, hi, num[0], 0, &lo, &hi);	if (FLOAT_WORDS_BIG_ENDIAN)	  {	    num[0] = hi;	    num[1] = lo;	  }	else	  {	    num[0] = lo;	    num[1] = hi;	  }#ifdef REAL_ARITHMETIC	d = REAL_VALUE_FROM_TARGET_DOUBLE (num);#else	{	  union { double d;  jint i[2]; } u;	  u.i[0] = (jint) num[0];	  u.i[1] = (jint) num[1];	  d = u.d;	}#endif	value = build_real (double_type_node, d);	break;      }#endif /* TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT */    case CONSTANT_String:      {	extern struct obstack *expression_obstack;	tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));	char *utf8_ptr = IDENTIFIER_POINTER (name);	unsigned char *str_ptr;	int utf8_len = IDENTIFIER_LENGTH (name);	unsigned char *str = (unsigned char*)utf8_ptr;	int i = utf8_len;	int str_len;	/* Count the number of Unicode characters in the string,	   while checking for a malformed Utf8 string. */	for (str_len = 0; i > 0; str_len++)	  {	    int char_len = UT8_CHAR_LENGTH (*str);	    if (char_len < 0 || char_len > 2 || char_len > i)	      fatal ("bad string constant");	    str += char_len;	    i -= char_len;	  }	value = make_node (STRING_CST);	TREE_TYPE (value) = build_pointer_type (string_type_node);	TREE_STRING_LENGTH (value) = 2 * str_len;	TREE_STRING_POINTER (value)	  = obstack_alloc (expression_obstack, 2 * str_len);	str_ptr = (unsigned char *) TREE_STRING_POINTER (value);	str = (unsigned char*)utf8_ptr;	for (i = 0; i < str_len; i++)	  {	    int char_value;	    int char_len = UT8_CHAR_LENGTH (*str);	    switch (char_len)	      {	      case 1:		char_value = *str++;		break;	      case 2:		char_value = *str++ & 0x1F;		char_value = (char_value << 6) | (*str++ & 0x3F);		break;	      case 3:		char_value = *str_ptr++ & 0x0F;		char_value = (char_value << 6) | (*str++ & 0x3F);		char_value = (char_value << 6) | (*str++ & 0x3F);		break;	      default:		goto bad;	      }	    if (BYTES_BIG_ENDIAN)	      {		*str_ptr++ = char_value >> 8;		*str_ptr++ = char_value & 0xFF;	      }	    else	      {		*str_ptr++ = char_value & 0xFF;		*str_ptr++ = char_value >> 8;	      }	  }      }      break;    default:      goto bad;    }  pop_obstacks ();  JPOOL_TAG(jcf, index) = tag | CONSTANT_ResolvedFlag;  jcf->cpool.data [index] = (jword) value;  return value; bad:  fatal ("bad value constant type %d, index %d", 	 JPOOL_TAG( jcf, index ), index);}treeget_name_constant (jcf, index)  JCF *jcf;  int index;{  tree name = get_constant (jcf, index);  if (TREE_CODE (name) != IDENTIFIER_NODE)    fatal ("bad nameandtype index %d", index);  return name;}static treegive_name_to_class (jcf, i)     JCF *jcf;     int i;{  if (i <= 0 || i >= JPOOL_SIZE(jcf)      || JPOOL_TAG (jcf, i) != CONSTANT_Class)    fatal ("bad class index %d", i);  else    {      tree this_class;      int j = JPOOL_USHORT1 (jcf, i);      /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */      tree class_name = unmangle_classname (JPOOL_UTF_DATA (jcf, j),					    JPOOL_UTF_LENGTH (jcf, j));      this_class = lookup_class (class_name);      input_filename = DECL_SOURCE_FILE (TYPE_NAME (this_class));      lineno = 0;      if (main_input_filename == NULL && jcf == main_jcf)	main_input_filename = input_filename;      jcf->cpool.data[i] = (jword) this_class;      JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;      return this_class;    }}/* Get the class of the CONSTANT_Class whose constant pool index is I. */treeget_class_constant (JCF *jcf , int i){  tree type;  if (i <= 0 || i >= JPOOL_SIZE(jcf)      || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)    fatal ("bad class index %d", i);  if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)    {      int name_index = JPOOL_USHORT1 (jcf, i);      /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */      char *name = JPOOL_UTF_DATA (jcf, name_index);      int nlength = JPOOL_UTF_LENGTH (jcf, name_index);      if (name[0] == '[')  /* Handle array "classes". */	  type = TREE_TYPE (parse_signature_string (name, nlength));      else        {           tree cname = unmangle_classname (name, nlength);          type = lookup_class (cname);	}      jcf->cpool.data[i] = (jword) type;      JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;    }  else    type = (tree) jcf->cpool.data[i];  return type;}voidDEFUN(jcf_out_of_synch, (jcf),      JCF *jcf){  char *source = strdup (jcf->filename);  int i = strlen (source);  while (source[i] != '.')    i--;  source [i] = '\0';  warning ("Class file `%s' out of synch with `%s.java'", 	   jcf->filename, source);  free (source);}/* Read a class with the fully qualified-name NAME.   Return 1 iff we read the requested file.   (It is still possible we failed if the file did not   define the class it is supposed to.) */intread_class (name)     tree name;{  JCF this_jcf, *jcf;  tree save_current_class = current_class;  char *save_input_filename = input_filename;  JCF *save_current_jcf = current_jcf;  long saved_pos = 0;  if (current_jcf->read_state)    saved_pos = ftell (current_jcf->read_state);  push_obstacks (&permanent_obstack, &permanent_obstack);  /* Search in current zip first.  */  if (find_in_current_zip (IDENTIFIER_POINTER (name), &jcf) == 0)    /* 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 (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),		     &this_jcf, saw_java_source) == 0)      {	pop_obstacks ();	/* FIXME: one pop_obstack() per function */	return 0;      }    else      {        this_jcf.seen_in_zip = 0;        current_jcf = &this_jcf;	if (this_jcf.outofsynch)	  jcf_out_of_synch (current_jcf);      }  else    current_jcf = jcf;  if (current_jcf->java_source)    jcf_parse_source ();  else {    java_parser_context_save_global ();    java_push_parser_context ();    input_filename = current_jcf->filename;    jcf_parse (current_jcf);    java_pop_parser_context (0);    java_parser_context_restore_global ();  }  if (!current_jcf->seen_in_zip)    JCF_FINISH (current_jcf);  pop_obstacks ();  current_class = save_current_class;  input_filename = save_input_filename;  current_jcf = save_current_jcf;  if (current_jcf->read_state)    fseek (current_jcf->read_state, saved_pos, SEEK_SET);  return 1;}/* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if   called from the parser, otherwise it's a RECORD_TYPE node. If   VERBOSE is 1, print error message on failure to load a class. *//* Replace calls to load_class by having callers call read_class directly

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -