jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassWriter.java
changeset 12646 fa5227d43363
parent 12645 e0d32945f6ab
parent 12579 4cc5610a6dd6
child 12647 f9991bc4fdde
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassWriter.java	Thu May 10 20:05:12 2012 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,818 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
-
-import java.util.*;
-import java.lang.reflect.*;
-import java.io.*;
-import xmlkit.XMLKit.Element;
-/*
- * @author jrose
- */
-public class ClassWriter extends ClassSyntax implements ClassSyntax.GetCPIndex {
-
-    private static final CommandLineParser CLP = new CommandLineParser(""
-            + "-source:     +>  = \n"
-            + "-dest:       +>  = \n"
-            + "-encoding:   +>  = \n"
-            + "-parseBytes      $ \n"
-            + "-               *? \n"
-            + "\n");
-
-    public static void main(String[] ava) throws IOException {
-        ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
-        HashMap<String, String> props = new HashMap<String, String>();
-        props.put("-encoding:", "UTF8");  // default
-        CLP.parse(av, props);
-        File source = asFile(props.get("-source:"));
-        File dest = asFile(props.get("-dest:"));
-        String encoding = props.get("-encoding:");
-        boolean parseBytes = props.containsKey("-parseBytes");
-        boolean destMade = false;
-
-        for (String a : av) {
-            File f;
-            File inf = new File(source, a);
-            System.out.println("Reading " + inf);
-            Element e;
-            if (inf.getName().endsWith(".class")) {
-                ClassReader cr = new ClassReader();
-                cr.parseBytes = parseBytes;
-                e = cr.readFrom(inf);
-                f = new File(a);
-            } else if (inf.getName().endsWith(".xml")) {
-                InputStream in = new FileInputStream(inf);
-                Reader inw = ClassReader.makeReader(in, encoding);
-                e = XMLKit.readFrom(inw);
-                e.findAllInTree(XMLKit.and(XMLKit.elementFilter(nonAttrTags()),
-                        XMLKit.methodFilter(Element.method("trimText"))));
-                //System.out.println(e);
-                inw.close();
-                f = new File(a.substring(0, a.length() - ".xml".length()) + ".class");
-            } else {
-                System.out.println("Warning: unknown input " + a);
-                continue;
-            }
-            // Now write it:
-            if (!destMade) {
-                destMade = true;
-                if (dest == null) {
-                    dest = File.createTempFile("TestOut", ".dir", new File("."));
-                    dest.delete();
-                    System.out.println("Writing results to " + dest);
-                }
-                if (!(dest.isDirectory() || dest.mkdir())) {
-                    throw new RuntimeException("Cannot create " + dest);
-                }
-            }
-            File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
-            outf.getParentFile().mkdirs();
-            new ClassWriter(e).writeTo(outf);
-        }
-    }
-
-    private static File asFile(String str) {
-        return (str == null) ? null : new File(str);
-    }
-
-    public void writeTo(File file) throws IOException {
-        OutputStream out = null;
-        try {
-            out = new BufferedOutputStream(new FileOutputStream(file));
-            writeTo(out);
-        } finally {
-            if (out != null) {
-                out.close();
-            }
-        }
-    }
-    protected String[] callables;     // varies
-    protected int cpoolSize = 0;
-    protected HashMap<String, String> attrTypesByTag;
-    protected OutputStream out;
-    protected HashMap<String, int[]> cpMap = new HashMap<String, int[]>();
-    protected ArrayList<ByteArrayOutputStream> attrBufs = new ArrayList<ByteArrayOutputStream>();
-
-    private void setupAttrTypes() {
-        attrTypesByTag = new HashMap<String, String>();
-        for (String key : attrTypes.keySet()) {
-            String pfx = key.substring(0, key.indexOf('.') + 1);
-            String val = attrTypes.get(key);
-            int pos = val.indexOf('<');
-            if (pos >= 0) {
-                String tag = val.substring(pos + 1, val.indexOf('>', pos));
-                attrTypesByTag.put(pfx + tag, key);
-            }
-        }
-        //System.out.println("attrTypesByTag: "+attrTypesByTag);
-    }
-
-    protected ByteArrayOutputStream getAttrBuf() {
-        int nab = attrBufs.size();
-        if (nab == 0) {
-            return new ByteArrayOutputStream(1024);
-        }
-        ByteArrayOutputStream ab = attrBufs.get(nab - 1);
-        attrBufs.remove(nab - 1);
-        return ab;
-    }
-
-    protected void putAttrBuf(ByteArrayOutputStream ab) {
-        ab.reset();
-        attrBufs.add(ab);
-    }
-
-    public ClassWriter(Element root) {
-        this(root, null);
-    }
-
-    public ClassWriter(Element root, ClassSyntax cr) {
-        if (cr != null) {
-            attrTypes = cr.attrTypes;
-        }
-        setupAttrTypes();
-        if (root.getName() == "ClassFile") {
-            cfile = root;
-            cpool = root.findElement("ConstantPool");
-            klass = root.findElement("Class");
-        } else if (root.getName() == "Class") {
-            cfile = new Element("ClassFile",
-                    new String[]{
-                        "magic", String.valueOf(0xCAFEBABE),
-                        "minver", "0", "majver", "46",});
-            cpool = new Element("ConstantPool");
-            klass = root;
-        } else {
-            throw new IllegalArgumentException("bad element type " + root.getName());
-        }
-        if (cpool == null) {
-            cpool = new Element("ConstantPool");
-        }
-
-        int cpLen = 1 + cpool.size();
-        for (Element c : cpool.elements()) {
-            int id = (int) c.getAttrLong("id");
-            int tag = cpTagValue(c.getName());
-            setCPIndex(tag, c.getText().toString(), id);
-            switch (tag) {
-                case CONSTANT_Long:
-                case CONSTANT_Double:
-                    cpLen += 1;
-            }
-        }
-        cpoolSize = cpLen;
-    }
-
-    public int findCPIndex(int tag, String name) {
-        if (name == null) {
-            return 0;
-        }
-        int[] ids = cpMap.get(name.toString());
-        return (ids == null) ? 0 : ids[tag];
-    }
-
-    public int getCPIndex(int tag, String name) {
-        //System.out.println("getCPIndex "+cpTagName(tag)+" "+name);
-        if (name == null) {
-            return 0;
-        }
-        int id = findCPIndex(tag, name);
-        if (id == 0) {
-            id = cpoolSize;
-            cpoolSize += 1;
-            setCPIndex(tag, name, id);
-            cpool.add(new Element(cpTagName(tag),
-                    new String[]{"id", "" + id},
-                    new Object[]{name}));
-            int pos;
-            switch (tag) {
-                case CONSTANT_Long:
-                case CONSTANT_Double:
-                    cpoolSize += 1;
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                    getCPIndex(CONSTANT_Utf8, name);
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    pos = name.indexOf(' ');
-                    getCPIndex(CONSTANT_Class, name.substring(0, pos));
-                    getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1));
-                    break;
-                case CONSTANT_NameAndType:
-                    pos = name.indexOf(' ');
-                    getCPIndex(CONSTANT_Utf8, name.substring(0, pos));
-                    getCPIndex(CONSTANT_Utf8, name.substring(pos + 1));
-                    break;
-            }
-        }
-        return id;
-    }
-
-    public void setCPIndex(int tag, String name, int id) {
-        //System.out.println("setCPIndex id="+id+" tag="+tag+" name="+name);
-        int[] ids = cpMap.get(name);
-        if (ids == null) {
-            cpMap.put(name, ids = new int[13]);
-        }
-        if (ids[tag] != 0 && ids[tag] != id) {
-            System.out.println("Warning: Duplicate CP entries for " + ids[tag] + " and " + id);
-        }
-        //assert(ids[tag] == 0 || ids[tag] == id);
-        ids[tag] = id;
-    }
-
-    public int parseFlags(String flagString) {
-        int flags = 0;
-        int i = -1;
-        for (String[] names : modifierNames) {
-            ++i;
-            for (String name : names) {
-                if (name == null) {
-                    continue;
-                }
-                int pos = flagString.indexOf(name);
-                if (pos >= 0) {
-                    flags |= (1 << i);
-                }
-            }
-        }
-        return flags;
-    }
-
-    public void writeTo(OutputStream realOut) throws IOException {
-        OutputStream headOut = realOut;
-        ByteArrayOutputStream tailOut = new ByteArrayOutputStream();
-
-        // write the body of the class file first
-        this.out = tailOut;
-        writeClass();
-
-        // write the file header last
-        this.out = headOut;
-        u4((int) cfile.getAttrLong("magic"));
-        u2((int) cfile.getAttrLong("minver"));
-        u2((int) cfile.getAttrLong("majver"));
-        writeCP();
-
-        // recopy the file tail
-        this.out = null;
-        tailOut.writeTo(realOut);
-    }
-
-    void writeClass() throws IOException {
-        int flags = parseFlags(klass.getAttr("flags"));
-        flags ^= Modifier.SYNCHRONIZED;
-        u2(flags);
-        cpRef(CONSTANT_Class, klass.getAttr("name"));
-        cpRef(CONSTANT_Class, klass.getAttr("super"));
-        Element interfaces = klass.findAllElements("Interface");
-        u2(interfaces.size());
-        for (Element e : interfaces.elements()) {
-            cpRef(CONSTANT_Class, e.getAttr("name"));
-        }
-        for (int isMethod = 0; isMethod <= 1; isMethod++) {
-            Element members = klass.findAllElements(isMethod != 0 ? "Method" : "Field");
-            u2(members.size());
-            for (Element m : members.elements()) {
-                writeMember(m, isMethod != 0);
-            }
-        }
-        writeAttributesFor(klass);
-    }
-
-    private void writeMember(Element member, boolean isMethod) throws IOException {
-        //System.out.println("writeMember "+member);
-        u2(parseFlags(member.getAttr("flags")));
-        cpRef(CONSTANT_Utf8, member.getAttr("name"));
-        cpRef(CONSTANT_Utf8, member.getAttr("type"));
-        writeAttributesFor(member);
-    }
-
-    protected void writeAttributesFor(Element x) throws IOException {
-        LinkedHashSet<String> attrNames = new LinkedHashSet<String>();
-        for (Element e : x.elements()) {
-            attrNames.add(e.getName());  // uniquifying
-        }
-        attrNames.removeAll(nonAttrTags());
-        u2(attrNames.size());
-        if (attrNames.isEmpty()) {
-            return;
-        }
-        Element prevCurrent;
-        if (x.getName() == "Code") {
-            prevCurrent = currentCode;
-            currentCode = x;
-        } else {
-            prevCurrent = currentMember;
-            currentMember = x;
-        }
-        OutputStream realOut = this.out;
-        for (String utag : attrNames) {
-            String qtag = x.getName() + "." + utag;
-            String wtag = "*." + utag;
-            String key = attrTypesByTag.get(qtag);
-            if (key == null) {
-                key = attrTypesByTag.get(wtag);
-            }
-            String type = attrTypes.get(key);
-            //System.out.println("tag "+qtag+" => key "+key+"; type "+type);
-            Element attrs = x.findAllElements(utag);
-            ByteArrayOutputStream attrBuf = getAttrBuf();
-            if (type == null) {
-                if (attrs.size() != 1 || !attrs.get(0).equals(new Element(utag))) {
-                    System.out.println("Warning:  No attribute type description: " + qtag);
-                }
-                key = wtag;
-            } else {
-                try {
-                    this.out = attrBuf;
-                    // unparse according to type desc.
-                    if (type.equals("<Code>...")) {
-                        writeCode((Element) attrs.get(0));  // assume only 1
-                    } else if (type.equals("<Frame>...")) {
-                        writeStackMap(attrs, false);
-                    } else if (type.equals("<FrameX>...")) {
-                        writeStackMap(attrs, true);
-                    } else if (type.startsWith("[")) {
-                        writeAttributeRecursive(attrs, type);
-                    } else {
-                        writeAttribute(attrs, type);
-                    }
-                } finally {
-                    //System.out.println("Attr Bytes = \""+attrBuf.toString(EIGHT_BIT_CHAR_ENCODING).replace('"', (char)('"'|0x80))+"\"");
-                    this.out = realOut;
-                }
-            }
-            cpRef(CONSTANT_Utf8, key.substring(key.indexOf('.') + 1));
-            u4(attrBuf.size());
-            attrBuf.writeTo(out);
-            putAttrBuf(attrBuf);
-        }
-        if (x.getName() == "Code") {
-            currentCode = prevCurrent;
-        } else {
-            currentMember = prevCurrent;
-        }
-    }
-
-    private void writeAttributeRecursive(Element aval, String type) throws IOException {
-        assert (callables == null);
-        callables = getBodies(type);
-        writeAttribute(aval, callables[0]);
-        callables = null;
-    }
-
-    private void writeAttribute(Element aval, String type) throws IOException {
-        //System.out.println("writeAttribute "+aval+"  using "+type);
-        String nextAttrName = null;
-        boolean afterElemHead = false;
-        for (int len = type.length(), next, i = 0; i < len; i = next) {
-            int value;
-            char intKind;
-            int tag;
-            int sigChar;
-            String attrValue;
-            switch (type.charAt(i)) {
-                case '<':
-                    assert (nextAttrName == null);
-                    next = type.indexOf('>', i);
-                    String form = type.substring(i + 1, next++);
-                    if (form.indexOf('=') < 0) {
-                        //  elem_placement = '<' elemname '>'
-                        if (aval.isAnonymous()) {
-                            assert (aval.size() == 1);
-                            aval = (Element) aval.get(0);
-                        }
-                        assert (aval.getName().equals(form)) : aval + " // " + form;
-                        afterElemHead = true;
-                    } else {
-                        //  attr_placement = '(' attrname '=' (value)? ')'
-                        int eqPos = form.indexOf('=');
-                        assert (eqPos >= 0);
-                        nextAttrName = form.substring(0, eqPos).intern();
-                        if (eqPos != form.length() - 1) {
-                            // value is implicit, not placed in file
-                            nextAttrName = null;
-                        }
-                        afterElemHead = false;
-                    }
-                    continue;
-                case '(':
-                    next = type.indexOf(')', ++i);
-                    int callee = Integer.parseInt(type.substring(i, next++));
-                    writeAttribute(aval, callables[callee]);
-                    continue;
-                case 'N': // replication = 'N' int '[' type ... ']'
-                {
-                    assert (nextAttrName == null);
-                    afterElemHead = false;
-                    char countType = type.charAt(i + 1);
-                    next = i + 2;
-                    String type1 = getBody(type, next);
-                    Element elems = aval;
-                    if (type1.startsWith("<")) {
-                        // Select only matching members of aval.
-                        String elemName = type1.substring(1, type1.indexOf('>'));
-                        elems = aval.findAllElements(elemName);
-                    }
-                    putInt(elems.size(), countType);
-                    next += type1.length() + 2;  // skip body and brackets
-                    for (Element elem : elems.elements()) {
-                        writeAttribute(elem, type1);
-                    }
-                }
-                continue;
-                case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']'
-                    // write the value
-                    value = (int) aval.getAttrLong("tag");
-                    assert (aval.getAttr("tag") != null) : aval;
-                    intKind = type.charAt(++i);
-                    if (intKind == 'S') {
-                        intKind = type.charAt(++i);
-                    }
-                    putInt(value, intKind);
-                    nextAttrName = null;
-                    afterElemHead = false;
-                    ++i;  // skip the int type char
-                    // union_case = '(' ('-')? digit+ ')' '[' body ']'
-                    for (boolean foundCase = false;;) {
-                        assert (type.charAt(i) == '(');
-                        next = type.indexOf(')', ++i);
-                        assert (next >= i);
-                        String caseStr = type.substring(i, next++);
-                        String type1 = getBody(type, next);
-                        next += type1.length() + 2;  // skip body and brackets
-                        boolean lastCase = (caseStr.length() == 0);
-                        if (!foundCase
-                                && (lastCase || matchTag(value, caseStr))) {
-                            foundCase = true;
-                            // Execute this body.
-                            writeAttribute(aval, type1);
-                        }
-                        if (lastCase) {
-                            break;
-                        }
-                    }
-                    continue;
-                case 'B':
-                case 'H':
-                case 'I': // int = oneof "BHI"
-                    value = (int) aval.getAttrLong(nextAttrName);
-                    intKind = type.charAt(i);
-                    next = i + 1;
-                    break;
-                case 'K':
-                    sigChar = type.charAt(i + 1);
-                    if (sigChar == 'Q') {
-                        assert (currentMember.getName() == "Field");
-                        assert (aval.getName() == "ConstantValue");
-                        String sig = currentMember.getAttr("type");
-                        sigChar = sig.charAt(0);
-                        switch (sigChar) {
-                            case 'Z':
-                            case 'B':
-                            case 'C':
-                            case 'S':
-                                sigChar = 'I';
-                                break;
-                        }
-                    }
-                    switch (sigChar) {
-                        case 'I':
-                            tag = CONSTANT_Integer;
-                            break;
-                        case 'J':
-                            tag = CONSTANT_Long;
-                            break;
-                        case 'F':
-                            tag = CONSTANT_Float;
-                            break;
-                        case 'D':
-                            tag = CONSTANT_Double;
-                            break;
-                        case 'L':
-                            tag = CONSTANT_String;
-                            break;
-                        default:
-                            assert (false);
-                            tag = 0;
-                    }
-                    assert (type.charAt(i + 2) == 'H');  // only H works for now
-                    next = i + 3;
-                    assert (afterElemHead || nextAttrName != null);
-                    //System.out.println("get attr "+nextAttrName+" in "+aval);
-                    if (nextAttrName != null) {
-                        attrValue = aval.getAttr(nextAttrName);
-                        assert (attrValue != null);
-                    } else {
-                        assert (aval.isText()) : aval;
-                        attrValue = aval.getText().toString();
-                    }
-                    value = getCPIndex(tag, attrValue);
-                    intKind = 'H'; //type.charAt(i+2);
-                    break;
-                case 'R':
-                    sigChar = type.charAt(i + 1);
-                    switch (sigChar) {
-                        case 'C':
-                            tag = CONSTANT_Class;
-                            break;
-                        case 'S':
-                            tag = CONSTANT_Utf8;
-                            break;
-                        case 'D':
-                            tag = CONSTANT_Class;
-                            break;
-                        case 'F':
-                            tag = CONSTANT_Fieldref;
-                            break;
-                        case 'M':
-                            tag = CONSTANT_Methodref;
-                            break;
-                        case 'I':
-                            tag = CONSTANT_InterfaceMethodref;
-                            break;
-                        case 'U':
-                            tag = CONSTANT_Utf8;
-                            break;
-                        //case 'Q': tag = CONSTANT_Class; break;
-                        default:
-                            assert (false);
-                            tag = 0;
-                    }
-                    assert (type.charAt(i + 2) == 'H');  // only H works for now
-                    next = i + 3;
-                    assert (afterElemHead || nextAttrName != null);
-                    //System.out.println("get attr "+nextAttrName+" in "+aval);
-                    if (nextAttrName != null) {
-                        attrValue = aval.getAttr(nextAttrName);
-                    } else if (aval.hasText()) {
-                        attrValue = aval.getText().toString();
-                    } else {
-                        attrValue = null;
-                    }
-                    value = getCPIndex(tag, attrValue);
-                    intKind = 'H'; //type.charAt(i+2);
-                    break;
-                case 'P':  // bci = 'P' int
-                case 'S':  // signed_int = 'S' int
-                    next = i + 2;
-                    value = (int) aval.getAttrLong(nextAttrName);
-                    intKind = type.charAt(i + 1);
-                    break;
-                case 'F':
-                    next = i + 2;
-                    value = parseFlags(aval.getAttr(nextAttrName));
-                    intKind = type.charAt(i + 1);
-                    break;
-                default:
-                    throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type);
-            }
-            // write the value
-            putInt(value, intKind);
-            nextAttrName = null;
-            afterElemHead = false;
-        }
-        assert (nextAttrName == null);
-    }
-
-    private void putInt(int x, char ch) throws IOException {
-        switch (ch) {
-            case 'B':
-                u1(x);
-                break;
-            case 'H':
-                u2(x);
-                break;
-            case 'I':
-                u4(x);
-                break;
-        }
-        assert ("BHI".indexOf(ch) >= 0);
-    }
-
-    private void writeCode(Element code) throws IOException {
-        //System.out.println("writeCode "+code);
-        //Element m = new Element(currentMember); m.remove(code);
-        //System.out.println("       in "+m);
-        int stack = (int) code.getAttrLong("stack");
-        int local = (int) code.getAttrLong("local");
-        Element bytes = code.findElement("Bytes");
-        Element insns = code.findElement("Instructions");
-        String bytecodes;
-        if (insns == null) {
-            bytecodes = bytes.getText().toString();
-        } else {
-            bytecodes = InstructionSyntax.assemble(insns, this);
-            // Cache the assembled bytecodes:
-            bytes = new Element("Bytes", (String[]) null, bytecodes);
-            code.add(0, bytes);
-        }
-        u2(stack);
-        u2(local);
-        int length = bytecodes.length();
-        u4(length);
-        for (int i = 0; i < length; i++) {
-            u1((byte) bytecodes.charAt(i));
-        }
-        Element handlers = code.findAllElements("Handler");
-        u2(handlers.size());
-        for (Element handler : handlers.elements()) {
-            int start = (int) handler.getAttrLong("start");
-            int end = (int) handler.getAttrLong("end");
-            int catsh = (int) handler.getAttrLong("catch");
-            u2(start);
-            u2(end);
-            u2(catsh);
-            cpRef(CONSTANT_Class, handler.getAttr("class"));
-        }
-        writeAttributesFor(code);
-    }
-
-    protected void writeStackMap(Element attrs, boolean hasXOption) throws IOException {
-        Element bytes = currentCode.findElement("Bytes");
-        assert (bytes != null && bytes.size() == 1);
-        int byteLength = ((String) bytes.get(0)).length();
-        boolean uoffsetIsU4 = (byteLength >= (1 << 16));
-        boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16);
-        boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16);
-        if (uoffsetIsU4) {
-            u4(attrs.size());
-        } else {
-            u2(attrs.size());
-        }
-        for (Element frame : attrs.elements()) {
-            int bci = (int) frame.getAttrLong("bci");
-            if (uoffsetIsU4) {
-                u4(bci);
-            } else {
-                u2(bci);
-            }
-            if (hasXOption) {
-                u1((int) frame.getAttrLong("flags"));
-            }
-            // Scan local and stack types in this frame:
-            final int LOCALS = 0, STACK = 1;
-            for (int j = LOCALS; j <= STACK; j++) {
-                Element types = frame.findElement(j == LOCALS ? "Local" : "Stack");
-                int typeSize = (types == null) ? 0 : types.size();
-                if (j == LOCALS) {
-                    if (ulocalvarIsU4) {
-                        u4(typeSize);
-                    } else {
-                        u2(typeSize);
-                    }
-                } else { // STACK
-                    if (ustackIsU4) {
-                        u4(typeSize);
-                    } else {
-                        u2(typeSize);
-                    }
-                }
-                if (types == null) {
-                    continue;
-                }
-                for (Element type : types.elements()) {
-                    int tag = itemTagValue(type.getName());
-                    u1(tag);
-                    switch (tag) {
-                        case ITEM_Object:
-                            cpRef(CONSTANT_Class, type.getAttr("class"));
-                            break;
-                        case ITEM_Uninitialized:
-                        case ITEM_ReturnAddress: {
-                            int offset = (int) type.getAttrLong("bci");
-                            if (uoffsetIsU4) {
-                                u4(offset);
-                            } else {
-                                u2(offset);
-                            }
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    public void writeCP() throws IOException {
-        int cpLen = cpoolSize;
-        u2(cpLen);
-        ByteArrayOutputStream buf = getAttrBuf();
-        for (Element c : cpool.elements()) {
-            if (!c.isText()) {
-                System.out.println("## !isText " + c);
-            }
-            int id = (int) c.getAttrLong("id");
-            int tag = cpTagValue(c.getName());
-            String name = c.getText().toString();
-            int pos;
-            u1(tag);
-            switch (tag) {
-                case CONSTANT_Utf8: {
-                    int done = 0;
-                    buf.reset();
-                    int nameLen = name.length();
-                    while (done < nameLen) {
-                        int next = name.indexOf((char) 0, done);
-                        if (next < 0) {
-                            next = nameLen;
-                        }
-                        if (done < next) {
-                            buf.write(name.substring(done, next).getBytes(UTF8_ENCODING));
-                        }
-                        if (next < nameLen) {
-                            buf.write(0300);
-                            buf.write(0200);
-                            next++;
-                        }
-                        done = next;
-                    }
-                    u2(buf.size());
-                    buf.writeTo(out);
-                }
-                break;
-                case CONSTANT_Integer:
-                    u4(Integer.parseInt(name));
-                    break;
-                case CONSTANT_Float:
-                    u4(Float.floatToIntBits(Float.parseFloat(name)));
-                    break;
-                case CONSTANT_Long:
-                    u8(Long.parseLong(name));
-                    //i += 1;  // no need:  extra cp slot is implicit
-                    break;
-                case CONSTANT_Double:
-                    u8(Double.doubleToLongBits(Double.parseDouble(name)));
-                    //i += 1;  // no need:  extra cp slot is implicit
-                    break;
-                case CONSTANT_Class:
-                case CONSTANT_String:
-                    u2(getCPIndex(CONSTANT_Utf8, name));
-                    break;
-                case CONSTANT_Fieldref:
-                case CONSTANT_Methodref:
-                case CONSTANT_InterfaceMethodref:
-                    pos = name.indexOf(' ');
-                    u2(getCPIndex(CONSTANT_Class, name.substring(0, pos)));
-                    u2(getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1)));
-                    break;
-                case CONSTANT_NameAndType:
-                    pos = name.indexOf(' ');
-                    u2(getCPIndex(CONSTANT_Utf8, name.substring(0, pos)));
-                    u2(getCPIndex(CONSTANT_Utf8, name.substring(pos + 1)));
-                    break;
-            }
-        }
-        putAttrBuf(buf);
-    }
-
-    public void cpRef(int tag, String name) throws IOException {
-        u2(getCPIndex(tag, name));
-    }
-
-    public void u8(long x) throws IOException {
-        u4((int) (x >>> 32));
-        u4((int) (x >>> 0));
-    }
-
-    public void u4(int x) throws IOException {
-        u2(x >>> 16);
-        u2(x >>> 0);
-    }
-
-    public void u2(int x) throws IOException {
-        u1(x >>> 8);
-        u1(x >>> 0);
-    }
-
-    public void u1(int x) throws IOException {
-        out.write(x & 0xFF);
-    }
-}
-