All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.extendj.ast.BytecodeParser Maven / Gradle / Ivy

package org.extendj.ast;

import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.util.Set;
import beaver.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.LinkedHashSet;
import java.util.*;
import org.jastadd.util.PrettyPrintable;
import org.jastadd.util.PrettyPrinter;
import java.util.zip.*;
import java.io.*;
import org.jastadd.util.*;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
/**
 * @ast class
 * @aspect BytecodeReader
 * @declaredat /home/jesper/git/extendj/java8/frontend/BytecodeReader.jrag:35
 */
public class BytecodeParser extends AbstractClassfileParser implements Flags {
  

    public String outerClassName;

  

    public BytecodeParser(InputStream in, String name) {
      super(in, name);
    }

  

    @Override
    public boolean outerClassNameEquals(String name) {
      return outerClassName != null && outerClassName.equals(name);
    }

  

    public CompilationUnit parse(TypeDecl outerTypeDecl, String outerClassName,
        Program classPath, boolean isInner)
        throws FileNotFoundException, IOException {
      isInnerClass = isInner;
      return parse(outerTypeDecl, outerClassName, classPath);
    }

  

    public CompilationUnit parse(TypeDecl outerTypeDecl, String outerClassName, Program program)
        throws FileNotFoundException, IOException {

      if (VERBOSE) {
        println("Parsing byte codes in " + name);
      }

      try {
        this.outerClassName = outerClassName;
        parseMagic();
        int minor = parseMinor();
        int major = parseMajor();
        if (AbstractClassfileParser.VERBOSE) {
          println(String.format("Classfile version: %d.%d", major, minor));
        }
        if (major > 52) {
          error(String.format("Can not parse classfile version %d.%d."
                + " Classfile versions up to 52.x (Java 8) are supported by"
                + " this version of the compiler.",
                major, minor));
        }
        parseConstantPool();
        CompilationUnit cu = new CompilationUnit();
        TypeDecl typeDecl = parseTypeDecl();
        cu.setPackageDecl(classInfo.packageDecl());
        cu.addTypeDecl(typeDecl);
        parseFields(typeDecl);
        parseMethods(typeDecl);
        new Attributes.TypeAttributes(this, typeDecl, outerTypeDecl, program);
        return cu;
      } catch (Error e) {
        throw new IOException("Failed to parse classfile: " + name, e);
      }
    }

  

    public TypeDecl parseTypeDecl() throws IOException {
      int flags = u2();
      Modifiers modifiers = modifiers(flags & 0xfddf);
      if ((flags & (ACC_INTERFACE | ACC_ENUM)) == ACC_ENUM) {
        // Modifiers  /[SuperClass:Access]/ Implements:Access* BodyDecl*;
        EnumDecl decl = new EnumDecl();
        decl.setModifiers(modifiers);
        decl.setID(parseThisClass());
        Access superClass = parseSuperClass();
        // TODO trying to overwrite NTA?
        decl.setImplementsList(parseInterfaces(new List()));
        return decl;
      } else if ((flags & ACC_INTERFACE) == 0) {
        ClassDecl decl = new ClassDecl();
        decl.setModifiers(modifiers);
        decl.setID(parseThisClass());
        Access superClass = parseSuperClass();
        decl.setSuperClassOpt(
            superClass == null
            ? new Opt()
            : new Opt(superClass));
        decl.setImplementsList(parseInterfaces(new List()));
        return decl;
      } else if ((flags & ACC_ANNOTATION) == 0) {
        InterfaceDecl decl = new InterfaceDecl();
        decl.setModifiers(modifiers);
        decl.setID(parseThisClass());
        Access superClass = parseSuperClass();
        decl.setSuperInterfaceList(parseInterfaces(
            superClass == null
            ? new List()
            : new List().add(superClass)));
        return decl;
      } else {
        AnnotationDecl decl = new AnnotationDecl();
        decl.setModifiers(modifiers);
        decl.setID(parseThisClass());
        Access superClass = parseSuperClass();
        parseInterfaces(
            superClass == null
            ? new List()
            : new List().add(superClass));
        return decl;
      }
    }

  

    public static Access fromClassName(String s) {
      // Sample ClassName: a/b/c$d$e
      // the package name ends at the last '/'
      // after that follows a list of type names separated by '$'
      // all except the first are nested types

      String packageName = "";
      int index = s.lastIndexOf('/');
      if (index != -1) {
        packageName = s.substring(0, index).replace('/', '.');
      }
      String typeName = s.substring(index + 1, s.length());
      if (typeName.indexOf('$') != -1) {
        return new BytecodeTypeAccess(packageName, typeName);
      } else {
        return new TypeAccess(packageName, typeName);
      }
    }

  

    public void parseMethods(TypeDecl typeDecl) throws IOException {
      int count = u2();
      if (VERBOSE) {
        println("Methods (" + count + "):");
      }
      for (int i = 0; i < count; i++) {
        if (VERBOSE) {
          print("  Method nbr " + i + " ");
        }
        MethodInfo info = new MethodInfo(this);
        if (!info.isSynthetic() && !info.name.equals("")) {
          BodyDecl bodyDecl = info.bodyDecl();
          if (bodyDecl instanceof MethodDecl && typeDecl instanceof InterfaceDecl) {
            MethodDecl methodDecl = (MethodDecl) bodyDecl;
            boolean foundAbstract = false;
            boolean foundStatic = false;
            for (int j = 0; j < methodDecl.getModifiers().getNumModifier(); j++) {
              Modifier modifier = methodDecl.getModifiers().getModifier(j);
              if (modifier.getID().equals("abstract")) {
                foundAbstract = true;
              } else if (modifier.getID().equals("static")) {
                foundStatic = true;
              }
            }
            if (!foundAbstract && !foundStatic) {
              methodDecl.getModifiers().addModifier(new Modifier("default"));
            }
          }
          typeDecl.addBodyDecl(bodyDecl);
        }
      }
    }

  

    @Override
    public void parseConstantPoolEntry(int i) throws IOException {
      int tag = u1();
      switch (tag) {
        case CONSTANT_Class:
          constantPool[i] = new CONSTANT_Class_Info(this);
          break;
        case CONSTANT_FieldRef:
          constantPool[i] = new CONSTANT_Fieldref_Info(this);
          break;
        case CONSTANT_MethodRef:
          constantPool[i] = new CONSTANT_Methodref_Info(this);
          break;
        case CONSTANT_InterfaceMethodRef:
          constantPool[i] = new CONSTANT_InterfaceMethodref_Info(this);
          break;
        case CONSTANT_String:
          constantPool[i] = new CONSTANT_String_Info(this);
          break;
        case CONSTANT_Integer:
          constantPool[i] = new CONSTANT_Integer_Info(this);
          break;
        case CONSTANT_Float:
          constantPool[i] = new CONSTANT_Float_Info(this);
          break;
        case CONSTANT_Long:
          constantPool[i] = new CONSTANT_Long_Info(this);
          break;
        case CONSTANT_Double:
          constantPool[i] = new CONSTANT_Double_Info(this);
          break;
        case CONSTANT_NameAndType:
          constantPool[i] = new CONSTANT_NameAndType_Info(this);
          break;
        case CONSTANT_Utf8:
          constantPool[i] = new CONSTANT_Utf8_Info(this);
          break;
        case 15:
          u1();
          u2();
          break;
        case 16:
          u2();
          break;
        case 18:
          u2();
          u2();
        default:
          println("Unknown entry: " + tag);
      }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy