Index: src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java (revision 572724) +++ src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java (working copy) @@ -60,9 +60,24 @@ Codec.UNSIGNED5, attributeDefinitionCount, cpUTF8); attributeDefinitionLayout = parseReferences("attr_definition_layout", in, Codec.UNSIGNED5, attributeDefinitionCount, cpUTF8); - if (attributeDefinitionCount > 0) - throw new Error("No idea what the adc is for yet"); + attributeDefinitionMap = new AttributeLayoutMap(); + + int overflowIndex = 32; + if(segment.getSegmentHeader().getOptions().hasClassFlagsHi()) { + overflowIndex = 63; + } + for (int i = 0; i < attributeDefinitionCount; i++) { + int context = attributeDefinitionHeader[i] & 0x03; + int index = (attributeDefinitionHeader[i] >> 2) - 1; + if(index == -1) { + index = overflowIndex++; + } + attributeDefinitionMap.add(new AttributeLayout( + attributeDefinitionName[i], context, + attributeDefinitionLayout[i], index)); + } + attributeDefinitionMap.checkMap(); } public AttributeLayoutMap getAttributeDefinitionMap() { Index: src/main/java/org/apache/harmony/pack200/AttributeLayout.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttributeLayout.java (revision 572724) +++ src/main/java/org/apache/harmony/pack200/AttributeLayout.java (working copy) @@ -16,60 +16,8 @@ */ package org.apache.harmony.pack200; -// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5 -// NOTE: Do not extract strings as messages; this code is still a -// work-in-progress -// NOTE: Also, don't get rid of 'else' statements for the hell of it ... public class AttributeLayout implements IMatcher { - static class Key { - private final int context; - - private final String name; - - public Key(String name, int context) throws Pack200Exception { - if (name == null || name.length() == 0) - throw new Pack200Exception("Cannot have an unnamed layout"); - if (context != CONTEXT_CLASS && context != CONTEXT_CODE - && context != CONTEXT_FIELD && context != CONTEXT_METHOD) - throw new Pack200Exception("Attribute context out of range: " - + context); - this.name = name; - this.context = context; - - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Key other = (Key) obj; - if (context != other.context) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - - public int hashCode() { - final int PRIME = 31; - int result = 1; - result = PRIME * result + context; - result = PRIME * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - public String toString() { - return contextNames[context] + ": " + name; - } - - } public static final String ACC_ABSTRACT = "ACC_ABSTRACT"; //$NON-NLS-1$ public static final String ACC_ANNOTATION = "ACC_ANNOTATION"; //$NON-NLS-1$ @@ -103,11 +51,11 @@ public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; //$NON-NLS-1$ public static final String ATTRIBUTE_SIGNATURE = "Signature"; //$NON-NLS-1$ public static final String ATTRIBUTE_SOURCE_FILE = "SourceFile"; //$NON-NLS-1$ - public static final int CONTEXT_CLASS = 1 << 0; - public static final int CONTEXT_CODE = 1 << 4; - public static final int CONTEXT_FIELD = 1 << 2; - public static final int CONTEXT_METHOD = 1 << 3; - private static final String[] contextNames = { "Class", "Field", "Method", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + public static final int CONTEXT_CLASS = 0; + public static final int CONTEXT_CODE = 3; + public static final int CONTEXT_FIELD = 1; + public static final int CONTEXT_METHOD = 2; + public static final String[] contextNames = { "Class", "Field", "Method", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ "Code", }; //$NON-NLS-1$ private static Object getValue(String layout, long value, SegmentConstantPool pool) @@ -139,8 +87,11 @@ } throw new Pack200Exception("Unknown layout encoding: " + layout); } + + + private int context; - Key key; + private int index; private final String layout; @@ -145,6 +96,8 @@ private final String layout; private long mask; + + private String name; public AttributeLayout(String name, int context, String layout, int index) throws Pack200Exception { @@ -149,7 +102,8 @@ public AttributeLayout(String name, int context, String layout, int index) throws Pack200Exception { super(); - this.key = new Key(name, context); + this.index = index; + this.context = context; if (index >= 0) { this.mask = 1L << index; } else { @@ -155,11 +109,19 @@ } else { this.mask = 0; } + if (context != CONTEXT_CLASS && context != CONTEXT_CODE + && context != CONTEXT_FIELD && context != CONTEXT_METHOD) + throw new Pack200Exception("Attribute context out of range: " + + context); if (layout == null) // || layout.length() == 0) throw new Pack200Exception("Cannot have a null layout"); + if (name == null || name.length() == 0) + throw new Pack200Exception("Cannot have an unnamed layout"); + this.name = name; this.layout = layout; } - + + public boolean equals(Object obj) { if (this == obj) return true; @@ -168,11 +130,6 @@ if (getClass() != obj.getClass()) return false; final AttributeLayout other = (AttributeLayout) obj; - if (key == null) { - if (other.key != null) - return false; - } else if (!key.equals(other.key)) - return false; if (layout == null) { if (other.layout != null) return false; @@ -178,6 +135,15 @@ return false; } else if (!layout.equals(other.layout)) return false; + if(index != other.index) + return false; + if(context != other.context) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; return true; } @@ -231,23 +197,33 @@ } public int hashCode() { - return key.hashCode(); + int PRIME = 31; + int r = 1; + if(name != null) { + r = r * PRIME + name.hashCode(); + } + if(layout != null) { + r = r* PRIME + layout.hashCode(); + } + r = r * PRIME + index; + r = r * PRIME + context; + return r; } public boolean isClass() { - return key.context == CONTEXT_CLASS; + return context == CONTEXT_CLASS; } public boolean isCode() { - return key.context == CONTEXT_CODE; + return context == CONTEXT_CODE; } public boolean isField() { - return key.context == CONTEXT_FIELD; + return context == CONTEXT_FIELD; } public boolean isMethod() { - return key.context == CONTEXT_METHOD; + return context == CONTEXT_METHOD; } /* (non-Javadoc) @@ -258,7 +234,19 @@ } public String toString() { - return key.toString(); + return contextNames[context] + ": " + name; } + public int getContext() { + return context; + } + + public int getIndex() { + return index; + } + + public String getName() { + return name; + } + } Index: src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (revision 572384) +++ src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (working copy) @@ -21,6 +21,7 @@ // work-in-progress // NOTE: Also, don't get rid of 'else' statements for the hell of it ... import java.util.HashMap; +import java.util.Iterator; import java.util.Map; /** @@ -191,10 +192,16 @@ AttributeLayout.CONTEXT_METHOD, "*", 25) }; } - private final Map layouts; + private final Map classLayouts = new HashMap(); + private final Map fieldLayouts = new HashMap(); + private final Map methodLayouts = new HashMap(); + private final Map codeLayouts = new HashMap(); + + // The order of the maps in this array should not be changed as their indices correspond to + // the value of their context constants (AttributeLayout.CONTEXT_CLASS etc.) + private final Map[] layouts = new Map[] {classLayouts, fieldLayouts, methodLayouts, codeLayouts}; public AttributeLayoutMap() throws Pack200Exception { - this.layouts = new HashMap(); AttributeLayout[] defaultAttributeLayouts = getDefaultAttributeLayouts(); for (int i = 0; i < defaultAttributeLayouts.length; i++) { add(defaultAttributeLayouts[i]); @@ -202,7 +209,7 @@ } public void add(AttributeLayout layout) { - layouts.put(layout.key, layout); + layouts[layout.getContext()].put(Integer.valueOf(layout.getIndex()), layout); } public AttributeLayout getAttributeLayout(String name, int context) @@ -207,7 +214,45 @@ public AttributeLayout getAttributeLayout(String name, int context) throws Pack200Exception { - return (AttributeLayout) layouts.get(new AttributeLayout.Key(name, - context)); + Map map = layouts[context]; + for (Iterator iter = map.values().iterator(); iter.hasNext();) { + AttributeLayout layout = (AttributeLayout) iter.next(); + if(layout.getName().equals(name)) { + return layout; + } + } + return null; } + + /** + * The map should not contain the same layout and name combination more than + * once for each context. + * @throws Pack200Exception + * + */ + public void checkMap() throws Pack200Exception { + for (int i = 0; i < layouts.length; i++) { + Map map = layouts[i]; + for (Iterator iter = map.values().iterator(); iter.hasNext();) { + AttributeLayout layout1 = (AttributeLayout) iter.next(); + for (Iterator iter2 = map.values().iterator(); iter2.hasNext();) { + AttributeLayout layout2 = (AttributeLayout) iter2.next(); + if(layout1 != layout2) { + if (layout1.getName().equals(layout2.getName()) + && layout1.getLayout().equals( + layout2.getLayout())) { + throw new Pack200Exception( + "Same layout/name combination: " + + layout1.getLayout() + + "/" + + layout1.getName() + + " exists twice for context: " + + AttributeLayout.contextNames[layout1 + .getContext()]); + } + } + } + } + } + } } Index: src/main/java/org/apache/harmony/pack200/BHSDCodec.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BHSDCodec.java (revision 575301) +++ src/main/java/org/apache/harmony/pack200/BHSDCodec.java (working copy) @@ -171,12 +171,7 @@ } else { z = (long) (-Math.floor(u/ twoPowS) - 1); } - } else { - // TODO: This is required in the spec, but it's making a test fail so needs more investigation. - // z = cast32(u); } - - if (isDelta()) z += last; return z; Index: src/main/java/org/apache/harmony/pack200/BandSet.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BandSet.java (revision 572724) +++ src/main/java/org/apache/harmony/pack200/BandSet.java (working copy) @@ -119,7 +119,7 @@ } public long[] parseFlags(String name, InputStream in, int count, - Codec codec, boolean hasHi) throws IOException, Pack200Exception { + BHSDCodec codec, boolean hasHi) throws IOException, Pack200Exception { return parseFlags(name, in, 1, new int[] { count }, (hasHi ? codec : null), codec)[0]; } @@ -125,7 +125,7 @@ } public long[][] parseFlags(String name, InputStream in, int count, - int counts[], Codec codec, boolean hasHi) throws IOException, + int counts[], BHSDCodec codec, boolean hasHi) throws IOException, Pack200Exception { return parseFlags(name, in, count, counts, (hasHi ? codec : null), codec); @@ -132,7 +132,7 @@ } public long[][] parseFlags(String name, InputStream in, int count, - int counts[], Codec hiCodec, Codec loCodec) throws IOException, + int counts[], BHSDCodec hiCodec, BHSDCodec loCodec) throws IOException, Pack200Exception { // TODO Move away from decoding into a parseBand type structure if (count == 0) { @@ -139,26 +139,21 @@ return new long[][] { {} }; } long[][] result = new long[count][]; - // TODO What happens when the decode here indicates a different - // encoding? - // TODO Move this to a decodeBandInt - long last = 0; for (int j = 0; j < count; j++) { - result[j] = new long[counts[j]]; - for (int i = 0; i < counts[j] && hiCodec != null; i++) { - last = hiCodec.decode(in, last); - result[j][i] = last << 32; + int[] hi; + if(hiCodec != null) { + hi = decodeBandInt(name, in, hiCodec, counts[j]); + result[j] = decodeBandLong(name, in, loCodec, counts[j]); + for (int i = 0; i < counts[j]; i++) { + result[j][i] = (hi[i] << 32) |result[j][i]; + } + } else { + result[j] = decodeBandLong(name, in, loCodec, counts[j]); } } - last = 0; - for (int j = 0; j < count; j++) - for (int i = 0; i < counts[j]; i++) { - last = loCodec.decode(in, last); - result[j][i] = result[j][i] | last; - } // TODO Remove debugging code debug("Parsed *" + name + " (" + result.length + ")"); - return result; + return result; } /** @@ -263,9 +258,7 @@ * @deprecated this should be removed from production code */ protected void debug(String message) { - if (System.getProperty("debug.pack200") != null) { - System.err.println(message); - } + segment.debug(message); } Index: src/main/java/org/apache/harmony/pack200/Codec.java =================================================================== --- src/main/java/org/apache/harmony/pack200/Codec.java (revision 575301) +++ src/main/java/org/apache/harmony/pack200/Codec.java (working copy) @@ -249,6 +249,7 @@ public long[] decode(int n, InputStream in, long firstValue) throws IOException, Pack200Exception { long result[] = new long[n + 1]; + result[0] = firstValue; long last = firstValue; for(int i=1;i