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

com.googlecode.jpattern.org.cojen.classfile.CodeAssemblerPrinter Maven / Gradle / Ivy

Go to download

This is a copy of the good Cojen project from http://cojen.sourceforge.net/ with package name changed

The newest version!
/*
 *  Copyright 2004-2010 Brian S O'Neill
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.googlecode.jpattern.org.cojen.classfile;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.PrintWriter;

/**
 * CodeAssembler implementation that prints out instructions using a Java-like
 * syntax that matches the methods of CodeAssembler. When used in conjunction
 * with a {@link CodeDisassembler}, this class makes it easier to understand
 * how to use a CodeAssembler.
 *
 * @author Brian S O'Neill
 */
public class CodeAssemblerPrinter extends AbstractCodeAssembler implements CodeAssembler {
    private final LocalVariable[] mParams;
    private final boolean mIsStatic;
    private final PrintWriter mWriter;
    private final String mLinePrefix;
    private final String mLineSuffix;
    private final String mBulder;

    private boolean mNeedSeparatorLine;

    private int mLocalCounter;
    private int mLabelCounter;

    private int mTypeDescCounter;
    // Maps TypeDesc objects to String variable names.
    private Map mTypeDescNames;

    private int mTypeDescArrayCounter;
    // Maps TypeDesc arrays to String variable names.
    private Map, String> mTypeDescArrayNames;

    public CodeAssemblerPrinter(TypeDesc[] paramTypes, boolean isStatic,
                                PrintWriter writer)
    {
        this(paramTypes, isStatic, writer, null, null, null);
    }

    /**
     * @param linePrefix optional prefix for each line
     * @param lineSuffix optional suffix for each line
     * @param builder when specified, generated method calls are invoked on
     * local variable by this name
     */
    public CodeAssemblerPrinter(TypeDesc[] paramTypes, boolean isStatic,
                                PrintWriter writer,
                                String linePrefix, String lineSuffix,
                                String builder)
    {
        mIsStatic = isStatic;
        mWriter = writer;
        mLinePrefix = linePrefix;
        mLineSuffix = lineSuffix;
        if (builder == null || builder.length() == 0) {
            builder = "";
        } else if (!builder.endsWith(".")) {
            builder += '.';
        }
        mBulder = builder;
        mTypeDescNames = new HashMap();
        mTypeDescArrayNames = new HashMap, String>();

        mParams = new LocalVariable[paramTypes.length];

        int varNum = (isStatic) ? 0 : 1;
        for (int i = 0; i 0) {
                buf.append(", ");
            }
            buf.append(cases[i]);
        }
        buf.append("}");

        buf.append(", ");

        buf.append("new Location[] {");
        for (int i=0; i 0) {
                buf.append(", ");
            }
            buf.append(getLabelName(locations[i]));
        }
        buf.append("}");

        buf.append(", ");
        buf.append(getLabelName(defaultLocation));
        buf.append(')');

        println(buf.toString());
    }

    public void jsr(Location location) {
        println(mBulder + "jsr(" + getLabelName(location) + ')');
    }

    public void ret(LocalVariable local) {
        println(mBulder + "ret(" + local.getName() + ')');
    }

    public void math(byte opcode) {
        println
            (mBulder + "math(Opcode." + Opcode.getMnemonic(opcode).toUpperCase() + ')');
    }

    public void arrayLength() {
        println(mBulder + "arrayLength()");
    }

    public void throwObject() {
        println(mBulder + "throwObject()");
    }

    public void checkCast(TypeDesc type) {
        println(mBulder + "checkCast(" + getTypeDescName(type) + ')');
    }

    public void instanceOf(TypeDesc type) {
        println(mBulder + "instanceOf(" + getTypeDescName(type) + ')');
    }

    public void integerIncrement(LocalVariable local, int amount) {
        println(mBulder + "integerIncrement(" + local.getName() + ", " + amount + ')');
    }

    public void monitorEnter() {
        println(mBulder + "monitorEnter()");
    }

    public void monitorExit() {
        println(mBulder + "monitorExit()");
    }

    public void nop() {
        println(mBulder + "nop()");
    }

    public void breakpoint() {
        println(mBulder + "breakpoint()");
    }

    private void separatorLine() {
        if (mNeedSeparatorLine) {
            mWriter.println();
            mNeedSeparatorLine = false;
        }
    }

    private void println(String str) {
        mNeedSeparatorLine = true;
        if (mLinePrefix != null) {
            mWriter.print(mLinePrefix);
        }
        if (mLineSuffix == null) {
            mWriter.println(str);
        } else {
            mWriter.print(str);
            mWriter.println(mLineSuffix);
        }
    }

    private String getLabelName(Location location) {
        if (location instanceof NamedLabel) {
            return ((NamedLabel)location).mName;
        } else {
            return ((NamedLabel)createLabel()).mName;
        }
    }

    private String getTypeDescName(TypeDesc type) {
        if (type == null) {
            return "null";
        }

        String name = mTypeDescNames.get(type);

        if (name == null) {
            if (type.isPrimitive()) {
                name = "TypeDesc.".concat(type.getRootName().toUpperCase());
                mTypeDescNames.put(type, name);
                return name;
            } else if (type == TypeDesc.OBJECT) {
                mTypeDescNames.put(type, name = "TypeDesc.OBJECT");
                return name;
            } else if (type == TypeDesc.STRING) {
                mTypeDescNames.put(type, name = "TypeDesc.STRING");
                return name;
            }

            name = "type_" + (++mTypeDescCounter);
            mTypeDescNames.put(type, name);

            StringBuffer buf = new StringBuffer("TypeDesc ");
            buf.append(name);
            buf.append(" = ");

            TypeDesc componentType = type.getComponentType();
            if (componentType != null) {
                buf.append(getTypeDescName(componentType));
                buf.append(".toArrayType(");
            } else {
                buf.append("TypeDesc.forClass(");
                buf.append('"');
                buf.append(type.getRootName());
                buf.append('"');
            }

            buf.append(')');
            println(buf.toString());
        }

        return name;
    }

    private String getTypeDescArrayName(TypeDesc[] types) {
        if (types == null) {
            return "null";
        }

        List key = Arrays.asList(types);
        String name = mTypeDescArrayNames.get(key);

        if (name == null) {
            name = "params_" + (++mTypeDescArrayCounter);
            mTypeDescArrayNames.put(key, name);

            StringBuffer buf = new StringBuffer("TypeDesc[] ");
            buf.append(name);
            buf.append(" = new TypeDesc[] {");

            for (int i=0; i 0) {
                    buf.append(", ");
                }
                buf.append(getTypeDescName(types[i]));
            }

            buf.append('}');
            println(buf.toString());
        }

        return name;
    }

    static String escape(String value) {
        return escape(value, false);
    }

    static String escape(String value, boolean forChar) {
        int length = value.length();
        int i = 0;
        for (; i < length; i++) {
            char c = value.charAt(i);
            if (c < 32 || c > 126 || c == '"' || c == '\\' || (forChar && c == '\'')) {
                break;
            }
        }

        if (i >= length) {
            return value;
        }

        StringBuffer buf = new StringBuffer(length + 16);
        for (i=0; i= 32 && c <= 126 && c != '"' && c != '\\' && (!forChar || c != '\'')) {
                buf.append(c);
                continue;
            }

            switch (c) {
            case '\0':
                buf.append("\\0");
                break;
            case '"':
                buf.append("\\\"");
                break;
            case '\'':
                buf.append("\\'");
                break;
            case '\\':
                buf.append("\\\\");
                break;
            case '\b':
                buf.append("\\b");
                break;
            case '\f':
                buf.append("\\f");
                break;
            case '\n':
                buf.append("\\n");
                break;
            case '\r':
                buf.append("\\r");
                break;
            case '\t':
                buf.append("\\t");
                break;
            default:
                String u = Integer.toHexString(c).toLowerCase();
                buf.append("\\u");
                for (int len = u.length(); len < 4; len++) {
                    buf.append('0');
                }
                buf.append(u);
                break;
            }
        }

        return buf.toString();
    }

    private class NamedLocal implements LocalVariable {
        private final String mName;
        private final TypeDesc mType;
        private final int mNumber;

        public NamedLocal(String name, TypeDesc type, int number) {
            mName = name;
            mType = type;
            mNumber = number;
        }

        public String getName() {
            return mName;
        }
        
        public void setName(String name) {
            println(mName + ".setName(" + name + ')');
        }
        
        public TypeDesc getType() {
            return mType;
        }
        
        public boolean isDoubleWord() {
            return mType.isDoubleWord();
        }
        
        public int getNumber() {
            return mNumber;
        }
        
        public Location getStartLocation() {
            return null;
        }
        
        public Location getEndLocation() {
            return null;
        }

        public Set getLocationRangeSet() {
            return null;
        }
    }

    private class NamedLabel implements Label {
        public final String mName;

        public NamedLabel(String name) {
            mName = name;
        }

        public Label setLocation() {
            println(mName + ".setLocation()");
            return this;
        }
        
        public int getLocation() {
            return -1;
        }

        public int compareTo(Location obj) {
            return 0;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy