/******************************************************************************
* Copyright (c) 2002 - 2014 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.shrikeCT;
import java.io.IOException;
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
import com.ibm.wala.sourcepos.CRTable;
import com.ibm.wala.sourcepos.MethodPositions;
import com.ibm.wala.sourcepos.Range;
public final class SourcePositionTableReader extends AttributeReader {
protected SourcePositionTableReader(AttrIterator attr) throws InvalidClassFileException {
super(attr, CRTable.ATTRIBUTE_NAME);
}
public static final class Position implements Comparable<Object> {
public final int firstLine;
public final int lastLine;
public final int firstCol;
public final int lastCol;
private Position(int firstLine, int lastLine, int firstCol, int lastCol) {
this.firstLine = firstLine;
this.lastLine = lastLine;
this.firstCol = firstCol;
this.lastCol = lastCol;
}
public int compareTo(Object o) {
if (o instanceof Position) {
Position p = (Position) o;
if (firstLine != p.firstLine) {
return firstLine - p.firstLine;
} else if (firstCol != p.firstCol) {
return firstCol - p.firstCol;
} else if (lastLine != p.lastLine) {
return lastLine - p.lastLine;
} else if (lastCol != p.lastCol) {
return lastCol - p.lastCol;
} else {
return 0;
}
} else {
return -1;
}
}
}
public static Position findParameterPosition(int methodNr, CodeReader code) throws InvalidClassFileException, IOException {
if (code == null) {
throw new IllegalArgumentException();
}
Position params = null;
// read parameter positions
{
ClassReader.AttrIterator cIter = new ClassReader.AttrIterator();
ClassReader cr = code.getClassReader();
cr.initMethodAttributeIterator(methodNr, cIter);
for (;cIter.isValid(); cIter.advance()) {
if (MethodPositions.ATTRIBUTE_NAME.equals(cIter.getName())) {
byte data[] = getData(cr, cIter.getRawOffset(), cIter.getRawSize());
MethodPositions mPos = new MethodPositions(data);
Range r = mPos.getMethodInfo();
params = convert(r);
}
}
}
return params;
}
public static Position[] makeBytecodeToPositionMap(CodeReader code) throws InvalidClassFileException, IOException {
if (code == null) {
throw new IllegalArgumentException();
}
Position pos[] = null;
ClassReader.AttrIterator iter = new ClassReader.AttrIterator();
code.initAttributeIterator(iter);
for (; iter.isValid(); iter.advance()) {
if (CRTable.ATTRIBUTE_NAME.equals(iter.getName())) {
if (pos == null) {
pos = new Position[code.getBytecodeLength()];
}
SourcePositionTableReader spRead = new SourcePositionTableReader(iter);
spRead.fillBytecodeToPositionMap(pos);
}
}
if (pos != null) {
// fill in gaps
Position last = new Position(0, 0, 0, 0);
for (int i = 0; i < pos.length; i++) {
Position cur = pos[i];
if (cur == null) {
pos[i] = last;
} else {
last = cur;
}
}
}
return pos;
}
private static final int ATTRIBUTE_HEADER_SIZE = 6;
private static final byte[] getData(ClassReader cr, int rawOffset, int rawSize) {
// prepare raw data of attribute to pass to sourceinfo
byte klass[] = cr.getBytes();
int size = rawSize - ATTRIBUTE_HEADER_SIZE;
byte data[] = new byte[size];
System.arraycopy(klass, rawOffset + ATTRIBUTE_HEADER_SIZE, data, 0, size);
return data;
}
private void fillBytecodeToPositionMap(Position[] pos) throws IOException {
byte tableData[] = getData(getClassReader(), getRawOffset(), getRawSize());
CRTable crTable = new CRTable(tableData);
for (int pc = 0; pc < pos.length; pc++) {
Range r = crTable.getSourceInfo(pc);
Position p = convert(r);
pos[pc] = p;
}
}
private final static Position convert(Range r) {
Position pos = null;
if (r != null) {
com.ibm.wala.sourcepos.Position start = r.getStartPosition();
com.ibm.wala.sourcepos.Position end = r.getEndPosition();
if (start != null && !start.isUndefined()) {
if (end != null && !end.isUndefined()) {
pos = new Position(start.getLine(), end.getLine(), start.getColumn(), end.getColumn());
} else {
pos = new Position(start.getLine(), start.getLine(), -1, -1);
}
}
}
return pos;
}
public static Position[] makeLineNumberToPositionMap(int[] lineNumberMap) {
Position pos[] = new Position[lineNumberMap.length];
for (int i = 0; i < pos.length; i++) {
int line = lineNumberMap[i];
pos[i] = new Position(line, line, -1, -1);
}
return pos;
}
}