001: /**
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000,2002,2003 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package oracle.toplink.libraries.asm.attrs;
030:
031: import oracle.toplink.libraries.asm.Attribute;
032: import oracle.toplink.libraries.asm.ByteVector;
033: import oracle.toplink.libraries.asm.ClassReader;
034: import oracle.toplink.libraries.asm.ClassWriter;
035: import oracle.toplink.libraries.asm.Label;
036:
037: /**
038: * The SourceDebugExtension attribute is an optional attribute defined in JSR-045
039: * in the attributes table of the ClassFile structure. There can be no more than one
040: * SourceDebugExtension attribute in the attributes table of a given ClassFile
041: * structure. The SourceDebugExtension attribute has the following format:
042: * <pre>
043: * SourceDebugExtension_attribute {
044: * u2 attribute_name_index;
045: * u4 attribute_length;
046: * u1 debug_extension[attribute_length];
047: * }
048: * </pre>
049: * The items of the SourceDebugExtension_attribute structure are as follows:
050: * <dl>
051: * <dt>attribute_name_index</dt>
052: * <dd>The value of the attribute_name_index item must be a valid index into the
053: * constant_pool table. The constant_pool entry at that index must be a
054: * CONSTANT_Utf8_info structure representing the string "SourceDebugExtension".</dd>
055: * <dt>attribute_length</dt>
056: * <dd>The value of the attribute_length item indicates the length of
057: * the attribute, excluding the initial six bytes. The value of the
058: * attribute_length item is thus the number of bytes in the debug_extension[]
059: * item.</dd>
060: * <dt>debug_extension[]</dt>
061: * <dd>The debug_extension array holds a string, which must be in UTF-8 format.
062: * There is no terminating zero byte. The string in the debug_extension item
063: * will be interpreted as extended debugging information. The content of this
064: * string has no semantic effect on the Java Virtual Machine.</dd>
065: * </dl>
066: *
067: * @see <a href="http://www.jcp.org/en/jsr/detail?id=45">JSR-045: Debugging
068: * Support for Other Languages</a>
069: *
070: * @author Eugene Kuleshov
071: */
072:
073: public class SourceDebugExtensionAttribute extends Attribute {
074:
075: public String debugExtension;
076:
077: public SourceDebugExtensionAttribute() {
078: super ("SourceDebugExtension");
079: }
080:
081: public SourceDebugExtensionAttribute(String debugExtension) {
082: this ();
083: this .debugExtension = debugExtension;
084: }
085:
086: protected Attribute read(ClassReader cr, int off, int len,
087: char[] buf, int codeOff, Label[] labels) {
088: return new SourceDebugExtensionAttribute(readUTF8(cr, off, len));
089: }
090:
091: protected ByteVector write(ClassWriter cw, byte[] code, int len,
092: int maxStack, int maxLocals) {
093: byte[] b = putUTF8(debugExtension);
094: return new ByteVector().putByteArray(b, 0, b.length);
095: }
096:
097: private String readUTF8(ClassReader cr, int index, int utfLen) {
098: int endIndex = index + utfLen;
099: byte[] b = cr.b;
100: char[] buf = new char[utfLen];
101: int strLen = 0;
102: int c, d, e;
103: while (index < endIndex) {
104: c = b[index++] & 0xFF;
105: switch (c >> 4) {
106: case 0:
107: case 1:
108: case 2:
109: case 3:
110: case 4:
111: case 5:
112: case 6:
113: case 7:
114: // 0xxxxxxx
115: buf[strLen++] = (char) c;
116: break;
117:
118: case 12:
119: case 13:
120: // 110x xxxx 10xx xxxx
121: d = b[index++];
122: buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
123: break;
124:
125: default:
126: // 1110 xxxx 10xx xxxx 10xx xxxx
127: d = b[index++];
128: e = b[index++];
129: buf[strLen++] = (char) (((c & 0x0F) << 12)
130: | ((d & 0x3F) << 6) | (e & 0x3F));
131: break;
132: }
133: }
134:
135: return new String(buf, 0, strLen);
136: }
137:
138: private byte[] putUTF8(String s) {
139: int charLength = s.length();
140: int byteLength = 0;
141: for (int i = 0; i < charLength; ++i) {
142: char c = s.charAt(i);
143: if (c >= '\001' && c <= '\177') {
144: byteLength++;
145: } else if (c > '\u07FF') {
146: byteLength += 3;
147: } else {
148: byteLength += 2;
149: }
150: }
151: /*if (byteLength > 65535) {
152: throw new IllegalArgumentException();
153: }*/
154: byte[] data = new byte[byteLength];
155: for (int i = 0; i < charLength;) {
156: char c = s.charAt(i);
157: if (c >= '\001' && c <= '\177') {
158: data[i++] = (byte) c;
159: } else if (c > '\u07FF') {
160: data[i++] = (byte) (0xE0 | c >> 12 & 0xF);
161: data[i++] = (byte) (0x80 | c >> 6 & 0x3F);
162: data[i++] = (byte) (0x80 | c & 0x3F);
163: } else {
164: data[i++] = (byte) (0xC0 | c >> 6 & 0x1F);
165: data[i++] = (byte) (0x80 | c & 0x3F);
166: }
167: }
168: return data;
169: }
170:
171: public String toString() {
172: return debugExtension;
173: }
174: }
|