0N/A/*
2362N/A * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.tools.jdi;
0N/A
0N/Aimport com.sun.jdi.*;
0N/A
0N/Aimport java.util.*;
0N/Aimport java.io.File;
0N/A
0N/Aclass SDE {
0N/A private static final int INIT_SIZE_FILE = 3;
0N/A private static final int INIT_SIZE_LINE = 100;
0N/A private static final int INIT_SIZE_STRATUM = 3;
0N/A
0N/A static final String BASE_STRATUM_NAME = "Java";
0N/A
0N/A /* for C capatibility */
0N/A static final String NullString = null;
0N/A
0N/A private class FileTableRecord {
0N/A int fileId;
0N/A String sourceName;
0N/A String sourcePath; // do not read - use accessor
0N/A boolean isConverted = false;
0N/A
0N/A /**
0N/A * Return the sourcePath, computing it if not set.
0N/A * If set, convert '/' in the sourcePath to the
0N/A * local file separator.
0N/A */
0N/A String getSourcePath(ReferenceTypeImpl refType) {
0N/A if (!isConverted) {
0N/A if (sourcePath == null) {
0N/A sourcePath = refType.baseSourceDir() + sourceName;
0N/A } else {
0N/A StringBuffer buf = new StringBuffer();
0N/A for (int i = 0; i < sourcePath.length(); ++i) {
0N/A char ch = sourcePath.charAt(i);
0N/A if (ch == '/') {
0N/A buf.append(File.separatorChar);
0N/A } else {
0N/A buf.append(ch);
0N/A }
0N/A }
0N/A sourcePath = buf.toString();
0N/A }
0N/A isConverted = true;
0N/A }
0N/A return sourcePath;
0N/A }
0N/A }
0N/A
0N/A private class LineTableRecord {
0N/A int jplsStart;
0N/A int jplsEnd;
0N/A int jplsLineInc;
0N/A int njplsStart;
0N/A int njplsEnd;
0N/A int fileId;
0N/A }
0N/A
0N/A private class StratumTableRecord {
0N/A String id;
0N/A int fileIndex;
0N/A int lineIndex;
0N/A }
0N/A
0N/A class Stratum {
0N/A private final int sti; /* stratum index */
0N/A
0N/A private Stratum(int sti) {
0N/A this.sti = sti;
0N/A }
0N/A
0N/A String id() {
0N/A return stratumTable[sti].id;
0N/A }
0N/A
0N/A boolean isJava() {
0N/A return sti == baseStratumIndex;
0N/A }
0N/A
0N/A /**
0N/A * Return all the sourceNames for this stratum.
0N/A * Look from our starting fileIndex upto the starting
0N/A * fileIndex of next stratum - can do this since there
0N/A * is always a terminator stratum.
0N/A * Default sourceName (the first one) must be first.
0N/A */
0N/A List<String> sourceNames(ReferenceTypeImpl refType) {
0N/A int i;
0N/A int fileIndexStart = stratumTable[sti].fileIndex;
0N/A /* one past end */
0N/A int fileIndexEnd = stratumTable[sti+1].fileIndex;
0N/A List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
0N/A for (i = fileIndexStart; i < fileIndexEnd; ++i) {
0N/A result.add(fileTable[i].sourceName);
0N/A }
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * Return all the sourcePaths for this stratum.
0N/A * Look from our starting fileIndex upto the starting
0N/A * fileIndex of next stratum - can do this since there
0N/A * is always a terminator stratum.
0N/A * Default sourcePath (the first one) must be first.
0N/A */
0N/A List<String> sourcePaths(ReferenceTypeImpl refType) {
0N/A int i;
0N/A int fileIndexStart = stratumTable[sti].fileIndex;
0N/A /* one past end */
0N/A int fileIndexEnd = stratumTable[sti+1].fileIndex;
0N/A List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
0N/A for (i = fileIndexStart; i < fileIndexEnd; ++i) {
0N/A result.add(fileTable[i].getSourcePath(refType));
0N/A }
0N/A return result;
0N/A }
0N/A
0N/A LineStratum lineStratum(ReferenceTypeImpl refType,
0N/A int jplsLine) {
0N/A int lti = stiLineTableIndex(sti, jplsLine);
0N/A if (lti < 0) {
0N/A return null;
0N/A } else {
0N/A return new LineStratum(sti, lti, refType,
0N/A jplsLine);
0N/A }
0N/A }
0N/A }
0N/A
0N/A class LineStratum {
0N/A private final int sti; /* stratum index */
0N/A private final int lti; /* line table index */
0N/A private final ReferenceTypeImpl refType;
0N/A private final int jplsLine;
0N/A private String sourceName = null;
0N/A private String sourcePath = null;
0N/A
0N/A private LineStratum(int sti, int lti,
0N/A ReferenceTypeImpl refType,
0N/A int jplsLine) {
0N/A this.sti = sti;
0N/A this.lti = lti;
0N/A this.refType = refType;
0N/A this.jplsLine = jplsLine;
0N/A }
0N/A
0N/A public boolean equals(Object obj) {
0N/A if ((obj != null) && (obj instanceof LineStratum)) {
0N/A LineStratum other = (LineStratum)obj;
0N/A return (lti == other.lti) &&
0N/A (sti == other.sti) &&
0N/A (lineNumber() == other.lineNumber()) &&
0N/A (refType.equals(other.refType));
0N/A } else {
0N/A return false;
0N/A }
0N/A }
0N/A
0N/A int lineNumber() {
0N/A return stiLineNumber(sti, lti, jplsLine);
0N/A }
0N/A
0N/A /**
0N/A * Fetch the source name and source path for
0N/A * this line, converting or constructing
0N/A * the source path if needed.
0N/A */
0N/A void getSourceInfo() {
0N/A if (sourceName != null) {
0N/A // already done
0N/A return;
0N/A }
0N/A int fti = stiFileTableIndex(sti, lti);
0N/A if (fti == -1) {
0N/A throw new InternalError(
0N/A "Bad SourceDebugExtension, no matching source id " +
0N/A lineTable[lti].fileId + " jplsLine: " + jplsLine);
0N/A }
0N/A FileTableRecord ftr = fileTable[fti];
0N/A sourceName = ftr.sourceName;
0N/A sourcePath = ftr.getSourcePath(refType);
0N/A }
0N/A
0N/A String sourceName() {
0N/A getSourceInfo();
0N/A return sourceName;
0N/A }
0N/A
0N/A String sourcePath() {
0N/A getSourceInfo();
0N/A return sourcePath;
0N/A }
0N/A }
0N/A
0N/A private FileTableRecord[] fileTable = null;
0N/A private LineTableRecord[] lineTable = null;
0N/A private StratumTableRecord[] stratumTable = null;
0N/A
0N/A private int fileIndex = 0;
0N/A private int lineIndex = 0;
0N/A private int stratumIndex = 0;
0N/A private int currentFileId = 0;
0N/A
0N/A private int defaultStratumIndex = -1;
0N/A private int baseStratumIndex = -2; /* so as not to match -1 above */
0N/A private int sdePos = 0;
0N/A
0N/A final String sourceDebugExtension;
0N/A String jplsFilename = null;
0N/A String defaultStratumId = null;
0N/A boolean isValid = false;
0N/A
0N/A SDE(String sourceDebugExtension) {
0N/A this.sourceDebugExtension = sourceDebugExtension;
0N/A decode();
0N/A }
0N/A
0N/A SDE() {
0N/A this.sourceDebugExtension = null;
0N/A createProxyForAbsentSDE();
0N/A }
0N/A
0N/A char sdePeek() {
0N/A if (sdePos >= sourceDebugExtension.length()) {
0N/A syntax();
0N/A }
0N/A return sourceDebugExtension.charAt(sdePos);
0N/A }
0N/A
0N/A char sdeRead() {
0N/A if (sdePos >= sourceDebugExtension.length()) {
0N/A syntax();
0N/A }
0N/A return sourceDebugExtension.charAt(sdePos++);
0N/A }
0N/A
0N/A void sdeAdvance() {
0N/A sdePos++;
0N/A }
0N/A
0N/A void syntax() {
0N/A throw new InternalError("bad SourceDebugExtension syntax - position " +
0N/A sdePos);
0N/A }
0N/A
0N/A void syntax(String msg) {
0N/A throw new InternalError("bad SourceDebugExtension syntax: " + msg);
0N/A }
0N/A
0N/A void assureLineTableSize() {
0N/A int len = lineTable == null? 0 : lineTable.length;
0N/A if (lineIndex >= len) {
0N/A int i;
0N/A int newLen = len == 0? INIT_SIZE_LINE : len * 2;
0N/A LineTableRecord[] newTable = new LineTableRecord[newLen];
0N/A for (i = 0; i < len; ++i) {
0N/A newTable[i] = lineTable[i];
0N/A }
0N/A for (; i < newLen; ++i) {
0N/A newTable[i] = new LineTableRecord();
0N/A }
0N/A lineTable = newTable;
0N/A }
0N/A }
0N/A
0N/A void assureFileTableSize() {
0N/A int len = fileTable == null? 0 : fileTable.length;
0N/A if (fileIndex >= len) {
0N/A int i;
0N/A int newLen = len == 0? INIT_SIZE_FILE : len * 2;
0N/A FileTableRecord[] newTable = new FileTableRecord[newLen];
0N/A for (i = 0; i < len; ++i) {
0N/A newTable[i] = fileTable[i];
0N/A }
0N/A for (; i < newLen; ++i) {
0N/A newTable[i] = new FileTableRecord();
0N/A }
0N/A fileTable = newTable;
0N/A }
0N/A }
0N/A
0N/A void assureStratumTableSize() {
0N/A int len = stratumTable == null? 0 : stratumTable.length;
0N/A if (stratumIndex >= len) {
0N/A int i;
0N/A int newLen = len == 0? INIT_SIZE_STRATUM : len * 2;
0N/A StratumTableRecord[] newTable = new StratumTableRecord[newLen];
0N/A for (i = 0; i < len; ++i) {
0N/A newTable[i] = stratumTable[i];
0N/A }
0N/A for (; i < newLen; ++i) {
0N/A newTable[i] = new StratumTableRecord();
0N/A }
0N/A stratumTable = newTable;
0N/A }
0N/A }
0N/A
0N/A String readLine() {
0N/A StringBuffer sb = new StringBuffer();
0N/A char ch;
0N/A
0N/A ignoreWhite();
0N/A while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
28N/A sb.append(ch);
0N/A }
0N/A // check for CR LF
0N/A if ((ch == '\r') && (sdePeek() == '\n')) {
0N/A sdeRead();
0N/A }
0N/A ignoreWhite(); // leading white
0N/A return sb.toString();
0N/A }
0N/A
0N/A private int defaultStratumTableIndex() {
0N/A if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {
0N/A defaultStratumIndex =
0N/A stratumTableIndex(defaultStratumId);
0N/A }
0N/A return defaultStratumIndex;
0N/A }
0N/A
0N/A int stratumTableIndex(String stratumId) {
0N/A int i;
0N/A
0N/A if (stratumId == null) {
0N/A return defaultStratumTableIndex();
0N/A }
0N/A for (i = 0; i < (stratumIndex-1); ++i) {
0N/A if (stratumTable[i].id.equals(stratumId)) {
0N/A return i;
0N/A }
0N/A }
0N/A return defaultStratumTableIndex();
0N/A }
0N/A
0N/A Stratum stratum(String stratumID) {
0N/A int sti = stratumTableIndex(stratumID);
0N/A return new Stratum(sti);
0N/A }
0N/A
0N/A List<String> availableStrata() {
0N/A List<String> strata = new ArrayList<String>();
0N/A
0N/A for (int i = 0; i < (stratumIndex-1); ++i) {
0N/A StratumTableRecord rec = stratumTable[i];
0N/A strata.add(rec.id);
0N/A }
0N/A return strata;
0N/A }
0N/A
0N/A/*****************************
0N/A * below functions/methods are written to compile under either Java or C
0N/A *
0N/A * Needed support functions:
0N/A * sdePeek()
0N/A * sdeRead()
0N/A * sdeAdvance()
0N/A * readLine()
0N/A * assureLineTableSize()
0N/A * assureFileTableSize()
0N/A * assureStratumTableSize()
0N/A * syntax()
0N/A *
0N/A * stratumTableIndex(String)
0N/A *
0N/A * Needed support variables:
0N/A * lineTable
0N/A * lineIndex
0N/A * fileTable
0N/A * fileIndex
0N/A * currentFileId
0N/A *
0N/A * Needed types:
0N/A * String
0N/A *
0N/A * Needed constants:
0N/A * NullString
0N/A */
0N/A
0N/A void ignoreWhite() {
0N/A char ch;
0N/A
0N/A while (((ch = sdePeek()) == ' ') || (ch == '\t')) {
0N/A sdeAdvance();
0N/A }
0N/A }
0N/A
0N/A void ignoreLine() {
0N/A char ch;
0N/A
0N/A while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
0N/A }
0N/A /* check for CR LF */
0N/A if ((ch == '\r') && (sdePeek() == '\n')) {
0N/A sdeAdvance();
0N/A }
0N/A ignoreWhite(); /* leading white */
0N/A }
0N/A
0N/A int readNumber() {
0N/A int value = 0;
0N/A char ch;
0N/A
0N/A ignoreWhite();
0N/A while (((ch = sdePeek()) >= '0') && (ch <= '9')) {
0N/A sdeAdvance();
0N/A value = (value * 10) + ch - '0';
0N/A }
0N/A ignoreWhite();
0N/A return value;
0N/A }
0N/A
0N/A void storeFile(int fileId, String sourceName, String sourcePath) {
0N/A assureFileTableSize();
0N/A fileTable[fileIndex].fileId = fileId;
0N/A fileTable[fileIndex].sourceName = sourceName;
0N/A fileTable[fileIndex].sourcePath = sourcePath;
0N/A ++fileIndex;
0N/A }
0N/A
0N/A void fileLine() {
0N/A int hasAbsolute = 0; /* acts as boolean */
0N/A int fileId;
0N/A String sourceName;
0N/A String sourcePath = null;
0N/A
0N/A /* is there an absolute filename? */
0N/A if (sdePeek() == '+') {
0N/A sdeAdvance();
0N/A hasAbsolute = 1;
0N/A }
0N/A fileId = readNumber();
0N/A sourceName = readLine();
0N/A if (hasAbsolute == 1) {
0N/A sourcePath = readLine();
0N/A }
0N/A
0N/A storeFile(fileId, sourceName, sourcePath);
0N/A }
0N/A
0N/A void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,
0N/A int njplsStart, int njplsEnd, int fileId) {
0N/A assureLineTableSize();
0N/A lineTable[lineIndex].jplsStart = jplsStart;
0N/A lineTable[lineIndex].jplsEnd = jplsEnd;
0N/A lineTable[lineIndex].jplsLineInc = jplsLineInc;
0N/A lineTable[lineIndex].njplsStart = njplsStart;
0N/A lineTable[lineIndex].njplsEnd = njplsEnd;
0N/A lineTable[lineIndex].fileId = fileId;
0N/A ++lineIndex;
0N/A }
0N/A
0N/A /**
0N/A * Parse line translation info. Syntax is
0N/A * <NJ-start-line> [ # <file-id> ] [ , <line-count> ] :
0N/A * <J-start-line> [ , <line-increment> ] CR
0N/A */
0N/A void lineLine() {
0N/A int lineCount = 1;
0N/A int lineIncrement = 1;
0N/A int njplsStart;
0N/A int jplsStart;
0N/A
0N/A njplsStart = readNumber();
0N/A
0N/A /* is there a fileID? */
0N/A if (sdePeek() == '#') {
0N/A sdeAdvance();
0N/A currentFileId = readNumber();
0N/A }
0N/A
0N/A /* is there a line count? */
0N/A if (sdePeek() == ',') {
0N/A sdeAdvance();
0N/A lineCount = readNumber();
0N/A }
0N/A
0N/A if (sdeRead() != ':') {
0N/A syntax();
0N/A }
0N/A jplsStart = readNumber();
0N/A if (sdePeek() == ',') {
0N/A sdeAdvance();
0N/A lineIncrement = readNumber();
0N/A }
0N/A ignoreLine(); /* flush the rest */
0N/A
0N/A storeLine(jplsStart,
0N/A jplsStart + (lineCount * lineIncrement) -1,
0N/A lineIncrement,
0N/A njplsStart,
0N/A njplsStart + lineCount -1,
0N/A currentFileId);
0N/A }
0N/A
0N/A /**
0N/A * Until the next stratum section, everything after this
0N/A * is in stratumId - so, store the current indicies.
0N/A */
0N/A void storeStratum(String stratumId) {
0N/A /* remove redundant strata */
0N/A if (stratumIndex > 0) {
0N/A if ((stratumTable[stratumIndex-1].fileIndex
0N/A == fileIndex) &&
0N/A (stratumTable[stratumIndex-1].lineIndex
0N/A == lineIndex)) {
0N/A /* nothing changed overwrite it */
0N/A --stratumIndex;
0N/A }
0N/A }
0N/A /* store the results */
0N/A assureStratumTableSize();
0N/A stratumTable[stratumIndex].id = stratumId;
0N/A stratumTable[stratumIndex].fileIndex = fileIndex;
0N/A stratumTable[stratumIndex].lineIndex = lineIndex;
0N/A ++stratumIndex;
0N/A currentFileId = 0;
0N/A }
0N/A
0N/A /**
0N/A * The beginning of a stratum's info
0N/A */
0N/A void stratumSection() {
0N/A storeStratum(readLine());
0N/A }
0N/A
0N/A void fileSection() {
0N/A ignoreLine();
0N/A while (sdePeek() != '*') {
0N/A fileLine();
0N/A }
0N/A }
0N/A
0N/A void lineSection() {
0N/A ignoreLine();
0N/A while (sdePeek() != '*') {
0N/A lineLine();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Ignore a section we don't know about.
0N/A */
0N/A void ignoreSection() {
0N/A ignoreLine();
0N/A while (sdePeek() != '*') {
0N/A ignoreLine();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * A base "Java" stratum is always available, though
0N/A * it is not in the SourceDebugExtension.
0N/A * Create the base stratum.
0N/A */
0N/A void createJavaStratum() {
0N/A baseStratumIndex = stratumIndex;
0N/A storeStratum(BASE_STRATUM_NAME);
0N/A storeFile(1, jplsFilename, NullString);
0N/A /* JPL line numbers cannot exceed 65535 */
0N/A storeLine(1, 65536, 1, 1, 65536, 1);
0N/A storeStratum("Aux"); /* in case they don't declare */
0N/A }
0N/A
0N/A /**
0N/A * Decode a SourceDebugExtension which is in SourceMap format.
0N/A * This is the entry point into the recursive descent parser.
0N/A */
0N/A void decode() {
0N/A /* check for "SMAP" - allow EOF if not ours */
0N/A if ((sourceDebugExtension.length() < 4) ||
0N/A (sdeRead() != 'S') ||
0N/A (sdeRead() != 'M') ||
0N/A (sdeRead() != 'A') ||
0N/A (sdeRead() != 'P')) {
0N/A return; /* not our info */
0N/A }
0N/A ignoreLine(); /* flush the rest */
0N/A jplsFilename = readLine();
0N/A defaultStratumId = readLine();
0N/A createJavaStratum();
0N/A while (true) {
0N/A if (sdeRead() != '*') {
0N/A syntax();
0N/A }
0N/A switch (sdeRead()) {
0N/A case 'S':
0N/A stratumSection();
0N/A break;
0N/A case 'F':
0N/A fileSection();
0N/A break;
0N/A case 'L':
0N/A lineSection();
0N/A break;
0N/A case 'E':
0N/A /* set end points */
0N/A storeStratum("*terminator*");
0N/A isValid = true;
0N/A return;
0N/A default:
0N/A ignoreSection();
0N/A }
0N/A }
0N/A }
0N/A
0N/A void createProxyForAbsentSDE() {
0N/A jplsFilename = null;
0N/A defaultStratumId = BASE_STRATUM_NAME;
0N/A defaultStratumIndex = stratumIndex;
0N/A createJavaStratum();
0N/A storeStratum("*terminator*");
0N/A }
0N/A
0N/A /***************** query functions ***********************/
0N/A
0N/A private int stiLineTableIndex(int sti, int jplsLine) {
0N/A int i;
0N/A int lineIndexStart;
0N/A int lineIndexEnd;
0N/A
0N/A lineIndexStart = stratumTable[sti].lineIndex;
0N/A /* one past end */
0N/A lineIndexEnd = stratumTable[sti+1].lineIndex;
0N/A for (i = lineIndexStart; i < lineIndexEnd; ++i) {
0N/A if ((jplsLine >= lineTable[i].jplsStart) &&
0N/A (jplsLine <= lineTable[i].jplsEnd)) {
0N/A return i;
0N/A }
0N/A }
0N/A return -1;
0N/A }
0N/A
0N/A private int stiLineNumber(int sti, int lti, int jplsLine) {
0N/A return lineTable[lti].njplsStart +
0N/A (((jplsLine - lineTable[lti].jplsStart) /
0N/A lineTable[lti].jplsLineInc));
0N/A }
0N/A
0N/A private int fileTableIndex(int sti, int fileId) {
0N/A int i;
0N/A int fileIndexStart = stratumTable[sti].fileIndex;
0N/A /* one past end */
0N/A int fileIndexEnd = stratumTable[sti+1].fileIndex;
0N/A for (i = fileIndexStart; i < fileIndexEnd; ++i) {
0N/A if (fileTable[i].fileId == fileId) {
0N/A return i;
0N/A }
0N/A }
0N/A return -1;
0N/A }
0N/A
0N/A private int stiFileTableIndex(int sti, int lti) {
0N/A return fileTableIndex(sti, lineTable[lti].fileId);
0N/A }
0N/A
0N/A boolean isValid() {
0N/A return isValid;
0N/A }
0N/A}