home *** CD-ROM | disk | FTP | other *** search
- // $Id: getclass.cpp,v 1.14 1999/09/01 14:58:25 shields Exp $
- //
- // This software is subject to the terms of the IBM Jikes Compiler
- // License Agreement available at the following URL:
- // http://www.ibm.com/research/jikes.
- // Copyright (C) 1996, 1998, International Business Machines Corporation
- // and others. All Rights Reserved.
- // You must accept the terms of that agreement to use this software.
- //
- #include "config.h"
- #include <sys/stat.h>
- #include "control.h"
- #include "semantic.h"
- #include "access.h"
- #include "getclass.h"
- #include "zip.h"
-
- inline u1 Semantic::GetU1(char *buffer)
- {
- return *buffer;
- }
-
- inline u2 Semantic::GetU2(char *buffer)
- {
- u2 i = (u1) *buffer++;
- return (i << 8) + (u1) *buffer;
- }
-
- inline u4 Semantic::GetU4(char *buffer)
- {
- u4 i = (u1) *buffer++;
- i = (i << 8) + (u1) *buffer++;
- i = (i << 8) + (u1) *buffer++;
- return (i << 8) + (u1) *buffer;
- }
-
- inline u1 Semantic::GetAndSkipU1(char *&buffer)
- {
- return (u1) *buffer++;
- }
-
- inline u2 Semantic::GetAndSkipU2(char *&buffer)
- {
- u2 i = (u1) *buffer++;
- return (i << 8) + (u1) *buffer++;
- }
-
- inline u4 Semantic::GetAndSkipU4(char *&buffer)
- {
- u4 i = (u1) *buffer++;
- i = (i << 8) + (u1) *buffer++;
- i = (i << 8) + (u1) *buffer++;
- return (i << 8) + (u1) *buffer++;
- }
-
- inline void Semantic::Skip(char *&buffer, int n)
- {
- buffer += n;
- }
-
-
- TypeSymbol *Semantic::ProcessNestedType(TypeSymbol *base_type, NameSymbol *name_symbol, LexStream::TokenIndex tok)
- {
- TypeSymbol *inner_type = base_type -> FindTypeSymbol(name_symbol);
- if (! inner_type)
- {
- int length = base_type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $
- wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
- wcscpy(external_name, base_type -> ExternalName());
- wcscat(external_name, StringConstant::US__DS);
- wcscat(external_name, name_symbol -> Name());
- NameSymbol *external_name_symbol = control.FindOrInsertName(external_name, length);
-
- delete [] external_name;
-
- inner_type = base_type -> InsertNestedTypeSymbol(name_symbol);
- inner_type -> outermost_type = base_type -> outermost_type;
- inner_type -> supertypes_closure = new SymbolSet;
- inner_type -> subtypes = new SymbolSet;
- inner_type -> SetExternalIdentity(external_name_symbol);
- inner_type -> SetOwner(base_type);
- inner_type -> SetSignature(control);
-
- FileSymbol *file_symbol = Control::GetFile(control, base_type -> ContainingPackage(), external_name_symbol);
- if (file_symbol)
- {
- inner_type -> file_symbol = file_symbol;
- inner_type -> SetLocation();
-
- ReadClassFile(inner_type, tok);
- }
- else
- {
- inner_type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
- inner_type -> super = control.Object();
- inner_type -> MarkBad();
- AddDefaultConstructor(inner_type);
- ReportSemError(SemanticError::TYPE_NOT_FOUND,
- tok,
- tok,
- inner_type -> ContainingPackage() -> PackageName(),
- inner_type -> ExternalName());
- }
- }
-
- return inner_type;
- }
-
-
- TypeSymbol *Semantic::RetrieveNestedTypes(TypeSymbol *base_type, wchar_t *signature, LexStream::TokenIndex tok)
- {
- int len;
- for (len = 0; signature[len] != U_NULL && signature[len] != U_DOLLAR; len++)
- ;
- NameSymbol *name_symbol = control.FindOrInsertName(signature, len);
- TypeSymbol *inner_type = ProcessNestedType(base_type, name_symbol, tok);
-
- return (signature[len] == U_DOLLAR ? RetrieveNestedTypes(inner_type, &signature[len + 1], tok) : inner_type);
- }
-
-
- TypeSymbol *Semantic::ReadTypeFromSignature(TypeSymbol *base_type, char *utf8_signature, int length, LexStream::TokenIndex tok)
- {
- TypeSymbol *type = control.type_table.FindType(utf8_signature, length);
-
- if (! type)
- {
- wchar_t *signature = new wchar_t[length + 1];
- (void) Control::ConvertUtf8ToUnicode(signature, utf8_signature, length);
-
- int total_length;
- for (total_length = 0; signature[total_length] != U_NULL && signature[total_length] != U_DOLLAR; total_length++)
- ;
-
- if (signature[total_length] != U_NULL && Code::IsDigit(signature[total_length + 1])) // an anonymous or a local type?
- {
- for (total_length += 2; Code::IsDigit(signature[total_length]); total_length++) // will stop at next '$' or '\0' !!!
- ;
- if (signature[total_length] != U_NULL) // not an anonymous type ? then, it's a local type: scan local name
- {
- for (total_length++; signature[total_length] != U_NULL && signature[total_length] != U_DOLLAR; total_length++)
- ;
- }
- }
-
- int len;
- for (len = total_length - 1; len >= 0 && signature[len] != U_SLASH; len--)
- ;
-
- wchar_t *name = &(signature[len + 1]);
-
- //
- // When a package name is specified in the signature, we look for the type in question
- // in that package, i.e., we redefine package. Otherwise, we search for the type in the
- // unnamed package.
- //
- PackageSymbol *package = NULL;
-
- //
- // Which package?
- //
- if (len >= 0)
- {
- wchar_t *package_name = new wchar_t[len + 1];
- for (int i = 0; i < len; i++)
- package_name[i] = signature[i];
- package_name[len] = U_NULL;
- package = control.ProcessPackage(package_name);
-
- if (package -> directory.Length() == 0)
- {
- ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
- tok,
- tok,
- package -> PackageName());
- }
- delete [] package_name;
- }
- else package = control.unnamed_package;
-
- //
- // Process type
- //
- NameSymbol *name_symbol = control.FindOrInsertName(name, total_length - (len + 1));
- type = package -> FindTypeSymbol(name_symbol);
- if (type)
- {
- if (type -> SourcePending())
- control.ProcessHeaders(type -> file_symbol);
- }
- else
- {
- FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
-
- //
- // If we are dealing with the unnamed package, ...
- //
- if ((! file_symbol) && package == control.unnamed_package)
- file_symbol = Control::GetFile(control, control.unnamed_package, name_symbol);
-
- //
- // If a file_symbol was not found, ReadType will issue an error message
- //
- type = ReadType(file_symbol, package, name_symbol, tok);
-
- //
- // If we have to do a full check and we have a case where a ".class" file
- // depends on a ".java" file then we should signal that the ".java" file
- // associated with the ".class" file should be recompiled.
- //
- if (control.option.full_check && (! control.option.depend) &&
- file_symbol && file_symbol -> IsJava() && (! file_symbol -> IsZip()))
- {
- control.recompilation_file_set.AddElement(file_symbol);
- if (! control.option.incremental && control.option.pedantic)
- {
- ReportSemError(SemanticError::RECOMPILATION,
- tok,
- tok,
- base_type -> ContainingPackage() -> Name(),
- base_type -> ExternalName(),
- type -> ContainingPackage() -> Name(),
- type -> ExternalName());
- }
- }
- }
-
- if (signature[total_length] == U_DOLLAR)
- type = RetrieveNestedTypes(type, &signature[total_length + 1], tok);
-
- delete [] signature;
- }
-
- //
- // Establish a dependence from base_type (read from a class file) to type.
- //
- AddDependence(base_type, type, tok);
-
- return type;
- }
-
-
- TypeSymbol *Semantic::ProcessSignature(TypeSymbol *base_type, char *signature, LexStream::TokenIndex tok)
- {
- TypeSymbol *type;
- int num_dimensions = 0;
-
- for (; *signature == U_LEFT_BRACKET; signature++)
- num_dimensions++;
-
- switch(*signature)
- {
- case U_B:
- type = control.byte_type;
- break;
- case U_C:
- type = control.char_type;
- break;
- case U_D:
- type = control.double_type;
- break;
- case U_F:
- type = control.float_type;
- break;
- case U_I:
- type = control.int_type;
- break;
- case U_J:
- type = control.long_type;
- break;
- case U_L:
- {
- //
- // The signature is of the form: "L<filename>;" - So, +1 to skip the 'L'
- // ReadTypeFromSignature considers a semicolon to be a terminator.
- //
- char *str = ++signature;
- while (*str != U_SEMICOLON)
- str++;
- type = ReadTypeFromSignature(base_type, signature, str - signature, tok);
- }
- break;
- case U_S:
- type = control.short_type;
- break;
- case U_Z:
- type = control.boolean_type;
- break;
- case U_V:
- type = control.void_type;
- break;
- default:
- assert(! "KNOW WHAT TO DO WITH SIGNATURE");
- break;
- }
-
- return (num_dimensions == 0 ? type : type -> GetArrayType((Semantic *)this, num_dimensions));
- }
-
-
- inline TypeSymbol *Semantic::GetClassPool(TypeSymbol *base_type,
- TypeSymbol **class_pool,
- char **constant_pool,
- int index,
- LexStream::TokenIndex tok)
- {
- if (! class_pool[index])
- {
- u2 name_index = Constant_Class_info::NameIndex(constant_pool[index]);
- char *str = Constant_Utf8_info::Bytes(constant_pool[name_index]);
-
- if (*str == U_LEFT_BRACKET)
- class_pool[index] = ProcessSignature(base_type, str, tok);
- else
- {
- u2 length = Constant_Utf8_info::Length(constant_pool[name_index]);
- char *p;
- for (p = &str[length - 1]; Code::IsDigit(*p); p--)
- ;
- if (*p != U_DOLLAR) // not an anonymous class
- class_pool[index] = ReadTypeFromSignature(base_type, str, length, tok);
- }
- }
-
- return class_pool[index];
- }
-
-
- void Semantic::ReadClassFile(TypeSymbol *type, LexStream::TokenIndex tok)
- {
- #ifdef TEST
- control.class_files_read++;
- #endif
-
- FileSymbol *file_symbol = type -> file_symbol;
-
- if (control.option.verbose) {
- Coutput << "[read "
- << file_symbol -> FileName()
- << "]\n";
- }
-
- if (file_symbol -> IsZip())
- {
- ZipFile *zipfile = new ZipFile(file_symbol);
-
- if (zipfile -> Buffer() == NULL)
- {
- type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
- if (type != control.Object())
- type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
- type -> MarkBad();
- AddDefaultConstructor(type);
-
- ReportSemError(SemanticError::COMPRESSED_ZIP_FILE,
- tok,
- tok,
- file_symbol -> PathSym() -> Name(),
- type -> ContainingPackage() -> PackageName(),
- type -> ExternalName());
- }
- else if (! ProcessClassFile(type, zipfile -> Buffer(), file_symbol -> uncompressed_size, tok))
- ProcessBadClass(type, tok);
-
- delete zipfile;
- }
- else
- {
- #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
- FILE *classfile = ::SystemFopen(file_symbol -> FileName(), "rb");
- if (classfile == NULL)
- {
- type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
- if (type != control.Object())
- type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
- type -> MarkBad();
- AddDefaultConstructor(type);
-
- ReportSemError(SemanticError::CANNOT_OPEN_CLASS_FILE,
- tok,
- tok,
- type -> ContainingPackage() -> PackageName(),
- type -> ExternalName());
- }
- else
- {
- struct stat status;
- ::SystemStat(file_symbol -> FileName(), &status);
-
- char *class_buffer = new char[status.st_size];
- fread(class_buffer, sizeof(char), status.st_size, classfile);
- fclose(classfile);
-
- if (! ProcessClassFile(type, class_buffer, status.st_size, tok))
- ProcessBadClass(type, tok);
-
- delete [] class_buffer;
- }
- #elif defined(WIN32_FILE_SYSTEM)
- HANDLE classfile = CreateFile(file_symbol -> FileName(), GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- HANDLE mapfile = (classfile == INVALID_HANDLE_VALUE
- ? classfile
- : CreateFileMapping(classfile, NULL, PAGE_READONLY, 0, 0, NULL));
-
- char *class_buffer = (mapfile == INVALID_HANDLE_VALUE ? NULL : (char *) MapViewOfFile(mapfile, FILE_MAP_READ, 0, 0, 0));
-
- if (class_buffer == NULL)
- {
- type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
- if (type != control.Object())
- type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
- type -> MarkBad();
- AddDefaultConstructor(type);
-
- ReportSemError(SemanticError::CANNOT_OPEN_CLASS_FILE,
- tok,
- tok,
- type -> ContainingPackage() -> PackageName(),
- type -> ExternalName());
- }
- else
- {
- DWORD high_order,
- size = GetFileSize(classfile, &high_order);
-
- size = (size == 0xFFFFFFFF && GetLastError() != NO_ERROR ? 0 : size);
-
- if (! ProcessClassFile(type, class_buffer, size, tok))
- ProcessBadClass(type, tok);
-
- UnmapViewOfFile(class_buffer);
- CloseHandle(mapfile);
- CloseHandle(classfile);
- }
- #endif
- }
-
- return;
- }
-
-
- void Semantic::ProcessBadClass(TypeSymbol *type, LexStream::TokenIndex tok)
- {
- if (! type -> Table()) // if there is no symbol table, add one
- type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
- if ((! type -> super) && type != control.Object()) // if there is no super type, add one
- type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
- type -> MarkBad();
- if (! type -> FindConstructorSymbol()) // if there are no constructors, add a default one
- AddDefaultConstructor(type);
-
- ReportSemError(SemanticError::INVALID_CLASS_FILE,
- tok,
- tok,
- type -> ContainingPackage() -> PackageName(),
- type -> ExternalName());
-
- return;
- }
-
-
- bool Semantic::ProcessClassFile(TypeSymbol *type, char *buffer, int buffer_size, LexStream::TokenIndex tok)
- {
- char *buffer_tail = &buffer[buffer_size];
-
- type -> MarkHeaderProcessed();
- type -> MarkConstructorMembersProcessed();
- type -> MarkMethodMembersProcessed();
- type -> MarkFieldMembersProcessed();
- type -> MarkLocalClassProcessingCompleted();
- type -> MarkSourceNoLongerPending();
-
- Skip(buffer, 8); // u4 magic;
- // u2 minor_version;
- // u2 major_version;
-
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 constant_pool_count = GetAndSkipU2(buffer);
- char **constant_pool = new char*[constant_pool_count];
- TypeSymbol **class_pool = (TypeSymbol **)
- memset(new TypeSymbol*[constant_pool_count], 0, constant_pool_count * sizeof(TypeSymbol *));
-
- constant_pool[0] = NULL;
- int *next_pool_index = new int[constant_pool_count],
- Class_root = 0,
- NameAndType_root = 0;
-
- for (int i = 1; i < constant_pool_count; i++)
- {
- constant_pool[i] = buffer;
- if (! InRange(buffer, buffer_tail, 1))
- return false;
- u1 tag = GetAndSkipU1(buffer);
- if (tag == Cp_Info::CONSTANT_Long || tag == Cp_Info::CONSTANT_Double)
- ++i; // skip the next entry for eight-byte constants
-
- u2 length;
- switch(tag)
- {
- case Cp_Info::CONSTANT_Utf8:
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- length = GetAndSkipU2(buffer);
- break;
- case Cp_Info::CONSTANT_Class:
- length = 2; // set_NameIndex(GetU2(classfile));
- next_pool_index[i] = Class_root; // save index of class constant
- Class_root = i;
- break;
- case Cp_Info::CONSTANT_String:
- length = 2; // set_NameIndex(GetU2(classfile));
- break;
- case Cp_Info::CONSTANT_NameAndType:
- length = 4; // set_class_index(GetU2(classfile)); set_name_and_type_index(GetU2(classfile));
- // or
- // set_NameIndex(GetU2(classfile)); set_DescriptorIndex(GetU2(classfile));
- // or
- // SetBytes(GetU4(classfile));
- next_pool_index[i] = NameAndType_root; // save index of class constant
- NameAndType_root = i;
- break;
- case Cp_Info::CONSTANT_Fieldref:
- case Cp_Info::CONSTANT_Methodref:
- case Cp_Info::CONSTANT_InterfaceMethodref:
- case Cp_Info::CONSTANT_Integer:
- case Cp_Info::CONSTANT_Float:
- length = 4; // set_class_index(GetU2(classfile)); set_name_and_type_index(GetU2(classfile));
- // or
- // set_NameIndex(GetU2(classfile)); set_DescriptorIndex(GetU2(classfile));
- // or
- // SetBytes(GetU4(classfile));
- break;
- case Cp_Info::CONSTANT_Long:
- case Cp_Info::CONSTANT_Double:
- length = 8; // set_HighBytes(GetU4(classfile));
- // set_LowBytes(GetU4(classfile));
-
- break;
- default:
- fprintf(stderr, "%s%d%s", "chaos: CODE \"", (int) tag, "\" is an invalid tag !!!\n");
- fflush(stderr);
- break;
- }
-
- Skip(buffer, length);
- }
-
- //
- // We are now ready to process this class file. If type is a nested
- // class, we will set its untransformed access flags properly later...
- //
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- type -> SetFlags(GetAndSkipU2(buffer));
-
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 this_class_index = GetAndSkipU2(buffer); // The index of this class
- u2 name_index = Constant_Class_info::NameIndex(constant_pool[this_class_index]);
- char *type_name = Constant_Utf8_info::Bytes(constant_pool[name_index]);
- u2 type_name_length = Constant_Utf8_info::Length(constant_pool[name_index]);
-
- int n;
- for (n = type_name_length; n >= 0 && type_name[n] != U_SLASH; n--)
- ;
-
- bool matched_package_names;
- if (type -> ContainingPackage() -> PackageNameLength() == n)
- {
- wchar_t *package_name = type -> ContainingPackage() -> PackageName();
- int i;
- for (i = 0; i < n && package_name[i] == type_name[i]; i++)
- ;
- matched_package_names = (i == n);
- }
- else matched_package_names = (n < 0 && type -> ContainingPackage() == control.unnamed_package);
-
- if (! matched_package_names)
- {
- type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
- if (type != control.Object())
- type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
- type -> MarkBad();
- AddDefaultConstructor(type);
-
- if (n < 0)
- n = 0;
- wchar_t *package_name = new wchar_t[n + 1];
- for (int i = 0; i < n; i++)
- package_name[i] = type_name[i];
- package_name[n] = U_NULL;
-
- if (type -> ContainingPackage() == control.unnamed_package)
- ReportSemError(SemanticError::TYPE_NOT_IN_UNNAMED_PACKAGE,
- tok,
- tok,
- type -> ExternalName(),
- type -> file_symbol -> directory_symbol -> PathSym() -> Name(),
- package_name);
- else ReportSemError(SemanticError::TYPE_IN_WRONG_PACKAGE,
- tok,
- tok,
- type -> ExternalName(),
- type -> ContainingPackage() -> PackageName(),
- package_name);
-
- delete [] package_name;
- }
- else
- {
- if ((! type -> IsNested()) && (n < 0)) // An outermost type contained in the unnamed package?
- {
- TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(type -> Identity());
- if (! old_type)
- control.unnamed_package_types.AddElement(type);
- else
- {
- ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
- tok,
- tok,
- type -> Name(),
- old_type -> FileLoc());
- }
- }
-
- //
- // On systems such as NT and Win-95 that are not case-sensitive,
- // we need to confirm that the type name specified matches the name
- // in the class file.
- //
- assert(type_name_length - (n + 1) == type -> ExternalNameLength());
-
- int i;
- for (i = 0; i < type -> ExternalNameLength(); i++)
- {
- if (type_name[(n + 1) + i] != type -> ExternalName()[i])
- break;
- }
- if (i < type -> ExternalNameLength())
- {
- wchar_t *name = new wchar_t[type_name_length + 1];
- for (int k = 0; k < type_name_length; k++)
- name[k] = type_name[k];
- name[type_name_length] = U_NULL;
- ReportSemError(SemanticError::TYPE_NAME_MISMATCH,
- tok,
- tok,
- type -> ContainingPackage() -> PackageName(),
- type -> ExternalName(),
- name);
- delete [] name;
- }
-
- //
- // ... Start doing real work !!!
- //
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 super_class = GetAndSkipU2(buffer);
- if (super_class)
- {
- type -> super = GetClassPool(type, class_pool, constant_pool, super_class, tok);
-
- type -> outermost_type -> supertypes_closure -> AddElement(type -> super -> outermost_type);
- type -> outermost_type -> supertypes_closure -> Union(*type -> super -> outermost_type -> supertypes_closure);
- }
-
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- for (int j = GetAndSkipU2(buffer); j > 0; j--)
- {
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 interface_index = GetAndSkipU2(buffer);
- type -> AddInterface(GetClassPool(type, class_pool, constant_pool, interface_index, tok));
-
- type -> outermost_type -> supertypes_closure -> AddElement(type -> super -> outermost_type);
- type -> outermost_type -> supertypes_closure -> Union(*type -> super -> outermost_type -> supertypes_closure);
- }
-
- //
- // Read all the fields
- //
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 fields_count = GetAndSkipU2(buffer);
- VariableSymbol **fields = new VariableSymbol*[fields_count];
- for (int k = 0; k < fields_count; k++)
- {
- if (! InRange(buffer, buffer_tail, 6))
- return false;
- u2 access_flags = GetAndSkipU2(buffer);
- u2 name_index = GetAndSkipU2(buffer);
- u2 descriptor_index = GetAndSkipU2(buffer);
-
- NameSymbol *name_symbol = control.ConvertUtf8ToUnicode(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- Constant_Utf8_info::Length(constant_pool[name_index]));
-
- VariableSymbol *symbol = new VariableSymbol(name_symbol);
- fields[k] = symbol;
-
- symbol -> SetOwner(type);
- symbol -> MarkComplete();
- symbol -> SetFlags(access_flags);
- symbol -> SetSignatureString(Constant_Utf8_info::Bytes(constant_pool[descriptor_index]),
- Constant_Utf8_info::Length(constant_pool[descriptor_index]));
-
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- int j = GetAndSkipU2(buffer);
- for (; j > 0; j--)
- {
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 name_index = GetAndSkipU2(buffer);
-
- if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_Synthetic_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_Synthetic, StringConstant::U8S_Synthetic_length * sizeof(char)) == 0)
- {
- symbol -> MarkSynthetic();
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, 4); // u4 attribute_length() { return attribute_length_; }
- // there is no info associated with a Synthetic attribute
- break; // If the field is synthetic, remaining attributes don't matter...
- }
- else if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_Deprecated_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_Deprecated, StringConstant::U8S_Deprecated_length * sizeof(char)) == 0)
- {
- symbol -> MarkDeprecated();
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, 4); // u4 attribute_length() { return attribute_length_; }
- // there is no info associated with a Deprecated attribute
- }
- else if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_ConstantValue_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_ConstantValue, StringConstant::U8S_ConstantValue_length * sizeof(char)) == 0)
- {
- Skip(buffer, 4); // u4 attribute_length;
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 constantvalue_index = GetAndSkipU2(buffer);
-
- u1 tag = Cp_Info::Tag(constant_pool[constantvalue_index]);
- if (tag == Cp_Info::CONSTANT_Integer)
- {
- int value = Constant_Integer_info::Value(constant_pool[constantvalue_index]);
- symbol -> initial_value = control.int_pool.FindOrInsert(value);
- }
- else if (tag == Cp_Info::CONSTANT_Long)
- {
- LongInt value = Constant_Long_info::Value(constant_pool[constantvalue_index]);
- symbol -> initial_value = control.long_pool.FindOrInsert(value);
- }
- else if (tag == Cp_Info::CONSTANT_Float)
- {
- IEEEfloat value = Constant_Float_info::Value(constant_pool[constantvalue_index]);
- symbol -> initial_value = control.float_pool.FindOrInsert(value);
- }
- else if (tag == Cp_Info::CONSTANT_Double)
- {
- IEEEdouble value = Constant_Double_info::Value(constant_pool[constantvalue_index]);
- symbol -> initial_value = control.double_pool.FindOrInsert(value);
- }
- else if (tag == Cp_Info::CONSTANT_String)
- {
- u2 string_index = Constant_String_info::StringIndex(constant_pool[constantvalue_index]);
- u2 length = Constant_Utf8_info::Length(constant_pool[string_index]);
- char *value = Constant_Utf8_info::Bytes(constant_pool[string_index]);
- symbol -> initial_value = control.Utf8_pool.FindOrInsert(value, length);
- }
- else if (tag == Cp_Info::CONSTANT_Utf8)
- {
- u2 length = Constant_Utf8_info::Length(constant_pool[constantvalue_index]);
- char *value = Constant_Utf8_info::Bytes(constant_pool[constantvalue_index]);
- symbol -> initial_value = control.Utf8_pool.FindOrInsert(value, length);
- }
- else
- {
- fprintf(stderr, "%s%d%s", "chaos: Constant tag \"", (int) tag, "\" is an invalid tag !!!\n");
- fflush(stderr);
- }
- }
- else
- {
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, GetAndSkipU4(buffer)); // u4 attribute_length() { return attribute_length_; }
- // u1 *info; /* info[attribute_length] */
- }
- }
-
- //
- // Skip remaining attributes
- //
- while (--j > 0)
- {
- Skip(buffer, 2); // u2 name_index
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, GetAndSkipU4(buffer)); // u4 attribute_length() { return attribute_length_; }
- // u1 *info; /* info[attribute_length] */
- }
- }
-
- //
- // Read all the methods
- //
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 methods_count = GetAndSkipU2(buffer);
- MethodSymbol **methods = new MethodSymbol*[methods_count];
- for (int l = 0; l < methods_count; l++)
- {
- if (! InRange(buffer, buffer_tail, 6))
- return false;
- u2 access_flags = GetAndSkipU2(buffer);
- u2 name_index = GetAndSkipU2(buffer);
- u2 descriptor_index = GetAndSkipU2(buffer);
-
- NameSymbol *name_symbol = control.ConvertUtf8ToUnicode(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- Constant_Utf8_info::Length(constant_pool[name_index]));
-
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- int j = GetAndSkipU2(buffer); // number of attributes
-
- if (name_symbol == control.clinit_name_symbol)
- {
- methods[l] = NULL;
- j++; // see the loop (way) below that skips the remaining attributes
- }
- else
- {
- MethodSymbol *method = new MethodSymbol(name_symbol);
- methods[l] = method;
-
- method -> SetContainingType(type);
- method -> SetFlags(access_flags);
-
- char *signature = Constant_Utf8_info::Bytes(constant_pool[descriptor_index]);
- int length = Constant_Utf8_info::Length(constant_pool[descriptor_index]);
-
- method -> SetSignature(control.Utf8_pool.FindOrInsert(signature, length));
-
- //
- // Read the exception that can be thrown by this method
- //
- for (; j > 0; j--)
- {
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 name_index = GetAndSkipU2(buffer);
-
- if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_Synthetic_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_Synthetic, StringConstant::U8S_Synthetic_length * sizeof(char)) == 0)
- {
- method -> MarkSynthetic();
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, 4); // u4 attribute_length() { return attribute_length_; }
- // there is no info associated with a Synthetic attribute
- break; // If the field is synthetic, remaining attributes don't matter...
- }
- else if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_Deprecated_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_Deprecated, StringConstant::U8S_Deprecated_length * sizeof(char)) == 0)
- {
- method -> MarkDeprecated();
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, 4); // u4 attribute_length() { return attribute_length_; }
- // there is no info associated with a Deprecated attribute
- }
- else if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_Exceptions_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_Exceptions, StringConstant::U8S_Exceptions_length * sizeof(char)) == 0)
- {
- Skip(buffer, 4); // attribute_length = GetAndSkipU4(buffer);
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- for (int k = GetAndSkipU2(buffer); k > 0; k--)
- {
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- int index = GetAndSkipU2(buffer);
- u2 name_index = Constant_Class_info::NameIndex(constant_pool[index]);
- method -> AddThrowsSignature(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- Constant_Utf8_info::Length(constant_pool[name_index]));
- }
- }
- else
- {
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, GetAndSkipU4(buffer)); // u4 attribute_length() { return attribute_length_; }
- // u1 *info; /* info[attribute_length] */
- }
- }
- }
-
- //
- // Skip remaining attributes
- //
- while (--j > 0)
- {
- Skip(buffer, 2); // u2 name_index
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, GetAndSkipU4(buffer)); // u4 attribute_length() { return attribute_length_; }
- // u1 *info; /* info[attribute_length] */
- }
- }
-
- //
- // Process InnerClasses attributes
- //
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 attributes_count = GetAndSkipU2(buffer);
- Tuple<u2> inner_name_indexes(8);
- for (int a = 0; a < attributes_count; a++)
- {
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- u2 name_index = GetAndSkipU2(buffer);
-
- if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_InnerClasses_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_InnerClasses, StringConstant::U8S_InnerClasses_length * sizeof(char)) == 0)
- {
- Skip(buffer, 4); // attribute_length = GetAndSkipU4(buffer);
- if (! InRange(buffer, buffer_tail, 2))
- return false;
- for (int k = GetAndSkipU2(buffer); k > 0; k--)
- {
- if (! InRange(buffer, buffer_tail, 8))
- return false;
- u2 inner_class_info_index = GetAndSkipU2(buffer);
- u2 outer_class_info_index = GetAndSkipU2(buffer);
- u2 inner_name_index = GetAndSkipU2(buffer);
- u2 inner_class_access_flags = GetAndSkipU2(buffer);
-
- //
- // Recall that the untransformed access flag is the one specified
- // in the inner_class attribute. (See 1.1 document)
- //
- if (inner_class_info_index == this_class_index)
- type -> SetFlags(inner_class_access_flags);
- //
- // This guard statement is used to identify only inner classes that are
- // not anonymous classes and are immediately contained within this class.
- // Recall that an inner class may not be enclosed (directly on indirectly)
- // in another class with the same name. Therefore when outer_class_info_index
- // matches this_class_index they both refer to "this" class (that we are currently processing).
- //
- else if ((outer_class_info_index == this_class_index) &&
- (inner_class_info_index != 0) && // an inner class
- (inner_name_index != 0)) // not an anonymous class
- {
- //
- // When length is 0, the inner class in question is "this" class ?
- // the one we are currently reading ?
- //
- u2 length = Constant_Utf8_info::Length(constant_pool[inner_name_index]);
- if (length > 0)
- inner_name_indexes.Next() = inner_name_index;
- }
- }
- }
- else if (Constant_Utf8_info::Length(constant_pool[name_index]) == StringConstant::U8S_Deprecated_length &&
- memcmp(Constant_Utf8_info::Bytes(constant_pool[name_index]),
- StringConstant::U8S_Deprecated, StringConstant::U8S_Deprecated_length * sizeof(char)) == 0)
- {
- type -> MarkDeprecated();
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, 4); // u4 attribute_length() { return attribute_length_; }
- // there is no info associated with a Deprecated attribute
- }
- else
- {
- if (! InRange(buffer, buffer_tail, 4))
- return false;
- Skip(buffer, GetAndSkipU4(buffer)); // u4 attribute_length() { return attribute_length_; }
- // u1 *info; /* info[attribute_length] */
- }
- }
-
- //
- // We now have enough information to make a good estimate for the size of the
- // symbol table we need for this class.
- //
- type -> SetSymbolTable(fields_count + methods_count + inner_name_indexes.Length());
-
- //
- // . Read in all class files that are referenced in CONSTANT_Class
- // structures in this class file.
- //
- // . Read in all class files that are referenced in CONSTANT_NameAndType
- // structures in this class file.
- //
- if (control.option.full_check && (control.option.unzip || (! type -> file_symbol -> IsZip())))
- {
- for (int h = Class_root; h != 0; h = next_pool_index[h])
- GetClassPool(type, class_pool, constant_pool, h, tok);
-
- for (int j = NameAndType_root; j != 0; j = next_pool_index[j])
- {
- u2 descriptor_index = Constant_NameAndType_info::DescriptorIndex(constant_pool[j]);
- char *signature = Constant_Utf8_info::Bytes(constant_pool[descriptor_index]);
-
- if (! class_pool[descriptor_index])
- {
- if (*signature != U_LEFT_PARENTHESIS) // ')' indicates a field descriptor
- class_pool[descriptor_index] = ProcessSignature(type,
- Constant_Utf8_info::Bytes(constant_pool[descriptor_index]),
- tok);
- else // a method descriptor
- {
- signature++; // +1 to skip initial '('
- while (*signature != U_RIGHT_PARENTHESIS)
- {
- char *str;
- for (str = signature; *str == U_LEFT_BRACKET; str++)
- ;
-
- if (*str == U_L)
- {
- for (str++; *str != U_SEMICOLON; str++)
- ;
- }
-
- int len = str - signature + 1;
- signature += len; // make signature point to next type
- }
- signature++; // skip L')'
-
- class_pool[descriptor_index] = ProcessSignature(type, signature, tok); // save the return type in first spot
- }
- }
- }
-
- //
- // Process all the fields, then the methods, then the inner types.
- // Read in all the types associated with the signatures.
- //
- for (int k = 0; k < fields_count; k++)
- {
- type -> InsertVariableSymbol(fields[k]);
- fields[k] -> ProcessVariableSignature((Semantic *) this, tok);
- }
-
- for (int l = 0; l < methods_count; l++)
- {
- if (methods[l])
- {
- MethodSymbol *method = type -> FindMethodSymbol(methods[l] -> name_symbol);
-
- if (! method)
- {
- if (methods[l] -> name_symbol == control.init_name_symbol)
- type -> InsertConstructorSymbol(methods[l]);
- else type -> InsertMethodSymbol(methods[l]);
- }
- else type -> Overload(method, methods[l]);
- methods[l] -> ProcessMethodSignature((Semantic *) this, tok);
- }
- }
-
- for (int m = 0; m < inner_name_indexes.Length(); m++)
- {
- u2 inner_name_index = inner_name_indexes[m];
- type -> AddNestedTypeSignature(Constant_Utf8_info::Bytes(constant_pool[inner_name_index]),
- Constant_Utf8_info::Length(constant_pool[inner_name_index]));
- }
- type -> ProcessNestedTypeSignatures((Semantic *) this, tok);
- }
- else
- {
- //
- // Process all the fields, then the methods, then the inner types.
- //
- for (int k = 0; k < fields_count; k++)
- type -> InsertVariableSymbol(fields[k]);
-
- for (int l = 0; l < methods_count; l++)
- {
- if (methods[l])
- {
- MethodSymbol *method = type -> FindMethodSymbol(methods[l] -> name_symbol);
-
- if (! method)
- {
- if (methods[l] -> name_symbol == control.init_name_symbol)
- type -> InsertConstructorSymbol(methods[l]);
- else type -> InsertMethodSymbol(methods[l]);
- }
- else type -> Overload(method, methods[l]);
- }
- }
-
- for (int m = 0; m < inner_name_indexes.Length(); m++)
- {
- u2 inner_name_index = inner_name_indexes[m];
- type -> AddNestedTypeSignature(Constant_Utf8_info::Bytes(constant_pool[inner_name_index]),
- Constant_Utf8_info::Length(constant_pool[inner_name_index]));
- }
- }
-
- delete [] fields;
- delete [] methods;
-
- //
- // Release extra space. This is an optimization.
- //
- type -> CompressSpace();
- }
-
- delete [] next_pool_index;
- delete [] class_pool;
- delete [] constant_pool;
-
- return true;
- }
-
-
-