--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/tools/jdi/SDE.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,686 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.jdi;
+
+import com.sun.jdi.*;
+
+import java.util.*;
+import java.io.File;
+
+class SDE {
+ private static final int INIT_SIZE_FILE = 3;
+ private static final int INIT_SIZE_LINE = 100;
+ private static final int INIT_SIZE_STRATUM = 3;
+
+ static final String BASE_STRATUM_NAME = "Java";
+
+ /* for C capatibility */
+ static final String NullString = null;
+
+ private class FileTableRecord {
+ int fileId;
+ String sourceName;
+ String sourcePath; // do not read - use accessor
+ boolean isConverted = false;
+
+ /**
+ * Return the sourcePath, computing it if not set.
+ * If set, convert '/' in the sourcePath to the
+ * local file separator.
+ */
+ String getSourcePath(ReferenceTypeImpl refType) {
+ if (!isConverted) {
+ if (sourcePath == null) {
+ sourcePath = refType.baseSourceDir() + sourceName;
+ } else {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < sourcePath.length(); ++i) {
+ char ch = sourcePath.charAt(i);
+ if (ch == '/') {
+ buf.append(File.separatorChar);
+ } else {
+ buf.append(ch);
+ }
+ }
+ sourcePath = buf.toString();
+ }
+ isConverted = true;
+ }
+ return sourcePath;
+ }
+ }
+
+ private class LineTableRecord {
+ int jplsStart;
+ int jplsEnd;
+ int jplsLineInc;
+ int njplsStart;
+ int njplsEnd;
+ int fileId;
+ }
+
+ private class StratumTableRecord {
+ String id;
+ int fileIndex;
+ int lineIndex;
+ }
+
+ class Stratum {
+ private final int sti; /* stratum index */
+
+ private Stratum(int sti) {
+ this.sti = sti;
+ }
+
+ String id() {
+ return stratumTable[sti].id;
+ }
+
+ boolean isJava() {
+ return sti == baseStratumIndex;
+ }
+
+ /**
+ * Return all the sourceNames for this stratum.
+ * Look from our starting fileIndex upto the starting
+ * fileIndex of next stratum - can do this since there
+ * is always a terminator stratum.
+ * Default sourceName (the first one) must be first.
+ */
+ List<String> sourceNames(ReferenceTypeImpl refType) {
+ int i;
+ int fileIndexStart = stratumTable[sti].fileIndex;
+ /* one past end */
+ int fileIndexEnd = stratumTable[sti+1].fileIndex;
+ List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
+ for (i = fileIndexStart; i < fileIndexEnd; ++i) {
+ result.add(fileTable[i].sourceName);
+ }
+ return result;
+ }
+
+ /**
+ * Return all the sourcePaths for this stratum.
+ * Look from our starting fileIndex upto the starting
+ * fileIndex of next stratum - can do this since there
+ * is always a terminator stratum.
+ * Default sourcePath (the first one) must be first.
+ */
+ List<String> sourcePaths(ReferenceTypeImpl refType) {
+ int i;
+ int fileIndexStart = stratumTable[sti].fileIndex;
+ /* one past end */
+ int fileIndexEnd = stratumTable[sti+1].fileIndex;
+ List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
+ for (i = fileIndexStart; i < fileIndexEnd; ++i) {
+ result.add(fileTable[i].getSourcePath(refType));
+ }
+ return result;
+ }
+
+ LineStratum lineStratum(ReferenceTypeImpl refType,
+ int jplsLine) {
+ int lti = stiLineTableIndex(sti, jplsLine);
+ if (lti < 0) {
+ return null;
+ } else {
+ return new LineStratum(sti, lti, refType,
+ jplsLine);
+ }
+ }
+ }
+
+ class LineStratum {
+ private final int sti; /* stratum index */
+ private final int lti; /* line table index */
+ private final ReferenceTypeImpl refType;
+ private final int jplsLine;
+ private String sourceName = null;
+ private String sourcePath = null;
+
+ private LineStratum(int sti, int lti,
+ ReferenceTypeImpl refType,
+ int jplsLine) {
+ this.sti = sti;
+ this.lti = lti;
+ this.refType = refType;
+ this.jplsLine = jplsLine;
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj != null) && (obj instanceof LineStratum)) {
+ LineStratum other = (LineStratum)obj;
+ return (lti == other.lti) &&
+ (sti == other.sti) &&
+ (lineNumber() == other.lineNumber()) &&
+ (refType.equals(other.refType));
+ } else {
+ return false;
+ }
+ }
+
+ int lineNumber() {
+ return stiLineNumber(sti, lti, jplsLine);
+ }
+
+ /**
+ * Fetch the source name and source path for
+ * this line, converting or constructing
+ * the source path if needed.
+ */
+ void getSourceInfo() {
+ if (sourceName != null) {
+ // already done
+ return;
+ }
+ int fti = stiFileTableIndex(sti, lti);
+ if (fti == -1) {
+ throw new InternalError(
+ "Bad SourceDebugExtension, no matching source id " +
+ lineTable[lti].fileId + " jplsLine: " + jplsLine);
+ }
+ FileTableRecord ftr = fileTable[fti];
+ sourceName = ftr.sourceName;
+ sourcePath = ftr.getSourcePath(refType);
+ }
+
+ String sourceName() {
+ getSourceInfo();
+ return sourceName;
+ }
+
+ String sourcePath() {
+ getSourceInfo();
+ return sourcePath;
+ }
+ }
+
+ private FileTableRecord[] fileTable = null;
+ private LineTableRecord[] lineTable = null;
+ private StratumTableRecord[] stratumTable = null;
+
+ private int fileIndex = 0;
+ private int lineIndex = 0;
+ private int stratumIndex = 0;
+ private int currentFileId = 0;
+
+ private int defaultStratumIndex = -1;
+ private int baseStratumIndex = -2; /* so as not to match -1 above */
+ private int sdePos = 0;
+
+ final String sourceDebugExtension;
+ String jplsFilename = null;
+ String defaultStratumId = null;
+ boolean isValid = false;
+
+ SDE(String sourceDebugExtension) {
+ this.sourceDebugExtension = sourceDebugExtension;
+ decode();
+ }
+
+ SDE() {
+ this.sourceDebugExtension = null;
+ createProxyForAbsentSDE();
+ }
+
+ char sdePeek() {
+ if (sdePos >= sourceDebugExtension.length()) {
+ syntax();
+ }
+ return sourceDebugExtension.charAt(sdePos);
+ }
+
+ char sdeRead() {
+ if (sdePos >= sourceDebugExtension.length()) {
+ syntax();
+ }
+ return sourceDebugExtension.charAt(sdePos++);
+ }
+
+ void sdeAdvance() {
+ sdePos++;
+ }
+
+ void syntax() {
+ throw new InternalError("bad SourceDebugExtension syntax - position " +
+ sdePos);
+ }
+
+ void syntax(String msg) {
+ throw new InternalError("bad SourceDebugExtension syntax: " + msg);
+ }
+
+ void assureLineTableSize() {
+ int len = lineTable == null? 0 : lineTable.length;
+ if (lineIndex >= len) {
+ int i;
+ int newLen = len == 0? INIT_SIZE_LINE : len * 2;
+ LineTableRecord[] newTable = new LineTableRecord[newLen];
+ for (i = 0; i < len; ++i) {
+ newTable[i] = lineTable[i];
+ }
+ for (; i < newLen; ++i) {
+ newTable[i] = new LineTableRecord();
+ }
+ lineTable = newTable;
+ }
+ }
+
+ void assureFileTableSize() {
+ int len = fileTable == null? 0 : fileTable.length;
+ if (fileIndex >= len) {
+ int i;
+ int newLen = len == 0? INIT_SIZE_FILE : len * 2;
+ FileTableRecord[] newTable = new FileTableRecord[newLen];
+ for (i = 0; i < len; ++i) {
+ newTable[i] = fileTable[i];
+ }
+ for (; i < newLen; ++i) {
+ newTable[i] = new FileTableRecord();
+ }
+ fileTable = newTable;
+ }
+ }
+
+ void assureStratumTableSize() {
+ int len = stratumTable == null? 0 : stratumTable.length;
+ if (stratumIndex >= len) {
+ int i;
+ int newLen = len == 0? INIT_SIZE_STRATUM : len * 2;
+ StratumTableRecord[] newTable = new StratumTableRecord[newLen];
+ for (i = 0; i < len; ++i) {
+ newTable[i] = stratumTable[i];
+ }
+ for (; i < newLen; ++i) {
+ newTable[i] = new StratumTableRecord();
+ }
+ stratumTable = newTable;
+ }
+ }
+
+ String readLine() {
+ StringBuffer sb = new StringBuffer();
+ char ch;
+
+ ignoreWhite();
+ while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
+ sb.append((char)ch);
+ }
+ // check for CR LF
+ if ((ch == '\r') && (sdePeek() == '\n')) {
+ sdeRead();
+ }
+ ignoreWhite(); // leading white
+ return sb.toString();
+ }
+
+ private int defaultStratumTableIndex() {
+ if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {
+ defaultStratumIndex =
+ stratumTableIndex(defaultStratumId);
+ }
+ return defaultStratumIndex;
+ }
+
+ int stratumTableIndex(String stratumId) {
+ int i;
+
+ if (stratumId == null) {
+ return defaultStratumTableIndex();
+ }
+ for (i = 0; i < (stratumIndex-1); ++i) {
+ if (stratumTable[i].id.equals(stratumId)) {
+ return i;
+ }
+ }
+ return defaultStratumTableIndex();
+ }
+
+ Stratum stratum(String stratumID) {
+ int sti = stratumTableIndex(stratumID);
+ return new Stratum(sti);
+ }
+
+ List<String> availableStrata() {
+ List<String> strata = new ArrayList<String>();
+
+ for (int i = 0; i < (stratumIndex-1); ++i) {
+ StratumTableRecord rec = stratumTable[i];
+ strata.add(rec.id);
+ }
+ return strata;
+ }
+
+/*****************************
+ * below functions/methods are written to compile under either Java or C
+ *
+ * Needed support functions:
+ * sdePeek()
+ * sdeRead()
+ * sdeAdvance()
+ * readLine()
+ * assureLineTableSize()
+ * assureFileTableSize()
+ * assureStratumTableSize()
+ * syntax()
+ *
+ * stratumTableIndex(String)
+ *
+ * Needed support variables:
+ * lineTable
+ * lineIndex
+ * fileTable
+ * fileIndex
+ * currentFileId
+ *
+ * Needed types:
+ * String
+ *
+ * Needed constants:
+ * NullString
+ */
+
+ void ignoreWhite() {
+ char ch;
+
+ while (((ch = sdePeek()) == ' ') || (ch == '\t')) {
+ sdeAdvance();
+ }
+ }
+
+ void ignoreLine() {
+ char ch;
+
+ while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
+ }
+ /* check for CR LF */
+ if ((ch == '\r') && (sdePeek() == '\n')) {
+ sdeAdvance();
+ }
+ ignoreWhite(); /* leading white */
+ }
+
+ int readNumber() {
+ int value = 0;
+ char ch;
+
+ ignoreWhite();
+ while (((ch = sdePeek()) >= '0') && (ch <= '9')) {
+ sdeAdvance();
+ value = (value * 10) + ch - '0';
+ }
+ ignoreWhite();
+ return value;
+ }
+
+ void storeFile(int fileId, String sourceName, String sourcePath) {
+ assureFileTableSize();
+ fileTable[fileIndex].fileId = fileId;
+ fileTable[fileIndex].sourceName = sourceName;
+ fileTable[fileIndex].sourcePath = sourcePath;
+ ++fileIndex;
+ }
+
+ void fileLine() {
+ int hasAbsolute = 0; /* acts as boolean */
+ int fileId;
+ String sourceName;
+ String sourcePath = null;
+
+ /* is there an absolute filename? */
+ if (sdePeek() == '+') {
+ sdeAdvance();
+ hasAbsolute = 1;
+ }
+ fileId = readNumber();
+ sourceName = readLine();
+ if (hasAbsolute == 1) {
+ sourcePath = readLine();
+ }
+
+ storeFile(fileId, sourceName, sourcePath);
+ }
+
+ void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,
+ int njplsStart, int njplsEnd, int fileId) {
+ assureLineTableSize();
+ lineTable[lineIndex].jplsStart = jplsStart;
+ lineTable[lineIndex].jplsEnd = jplsEnd;
+ lineTable[lineIndex].jplsLineInc = jplsLineInc;
+ lineTable[lineIndex].njplsStart = njplsStart;
+ lineTable[lineIndex].njplsEnd = njplsEnd;
+ lineTable[lineIndex].fileId = fileId;
+ ++lineIndex;
+ }
+
+ /**
+ * Parse line translation info. Syntax is
+ * <NJ-start-line> [ # <file-id> ] [ , <line-count> ] :
+ * <J-start-line> [ , <line-increment> ] CR
+ */
+ void lineLine() {
+ int lineCount = 1;
+ int lineIncrement = 1;
+ int njplsStart;
+ int jplsStart;
+
+ njplsStart = readNumber();
+
+ /* is there a fileID? */
+ if (sdePeek() == '#') {
+ sdeAdvance();
+ currentFileId = readNumber();
+ }
+
+ /* is there a line count? */
+ if (sdePeek() == ',') {
+ sdeAdvance();
+ lineCount = readNumber();
+ }
+
+ if (sdeRead() != ':') {
+ syntax();
+ }
+ jplsStart = readNumber();
+ if (sdePeek() == ',') {
+ sdeAdvance();
+ lineIncrement = readNumber();
+ }
+ ignoreLine(); /* flush the rest */
+
+ storeLine(jplsStart,
+ jplsStart + (lineCount * lineIncrement) -1,
+ lineIncrement,
+ njplsStart,
+ njplsStart + lineCount -1,
+ currentFileId);
+ }
+
+ /**
+ * Until the next stratum section, everything after this
+ * is in stratumId - so, store the current indicies.
+ */
+ void storeStratum(String stratumId) {
+ /* remove redundant strata */
+ if (stratumIndex > 0) {
+ if ((stratumTable[stratumIndex-1].fileIndex
+ == fileIndex) &&
+ (stratumTable[stratumIndex-1].lineIndex
+ == lineIndex)) {
+ /* nothing changed overwrite it */
+ --stratumIndex;
+ }
+ }
+ /* store the results */
+ assureStratumTableSize();
+ stratumTable[stratumIndex].id = stratumId;
+ stratumTable[stratumIndex].fileIndex = fileIndex;
+ stratumTable[stratumIndex].lineIndex = lineIndex;
+ ++stratumIndex;
+ currentFileId = 0;
+ }
+
+ /**
+ * The beginning of a stratum's info
+ */
+ void stratumSection() {
+ storeStratum(readLine());
+ }
+
+ void fileSection() {
+ ignoreLine();
+ while (sdePeek() != '*') {
+ fileLine();
+ }
+ }
+
+ void lineSection() {
+ ignoreLine();
+ while (sdePeek() != '*') {
+ lineLine();
+ }
+ }
+
+ /**
+ * Ignore a section we don't know about.
+ */
+ void ignoreSection() {
+ ignoreLine();
+ while (sdePeek() != '*') {
+ ignoreLine();
+ }
+ }
+
+ /**
+ * A base "Java" stratum is always available, though
+ * it is not in the SourceDebugExtension.
+ * Create the base stratum.
+ */
+ void createJavaStratum() {
+ baseStratumIndex = stratumIndex;
+ storeStratum(BASE_STRATUM_NAME);
+ storeFile(1, jplsFilename, NullString);
+ /* JPL line numbers cannot exceed 65535 */
+ storeLine(1, 65536, 1, 1, 65536, 1);
+ storeStratum("Aux"); /* in case they don't declare */
+ }
+
+ /**
+ * Decode a SourceDebugExtension which is in SourceMap format.
+ * This is the entry point into the recursive descent parser.
+ */
+ void decode() {
+ /* check for "SMAP" - allow EOF if not ours */
+ if ((sourceDebugExtension.length() < 4) ||
+ (sdeRead() != 'S') ||
+ (sdeRead() != 'M') ||
+ (sdeRead() != 'A') ||
+ (sdeRead() != 'P')) {
+ return; /* not our info */
+ }
+ ignoreLine(); /* flush the rest */
+ jplsFilename = readLine();
+ defaultStratumId = readLine();
+ createJavaStratum();
+ while (true) {
+ if (sdeRead() != '*') {
+ syntax();
+ }
+ switch (sdeRead()) {
+ case 'S':
+ stratumSection();
+ break;
+ case 'F':
+ fileSection();
+ break;
+ case 'L':
+ lineSection();
+ break;
+ case 'E':
+ /* set end points */
+ storeStratum("*terminator*");
+ isValid = true;
+ return;
+ default:
+ ignoreSection();
+ }
+ }
+ }
+
+ void createProxyForAbsentSDE() {
+ jplsFilename = null;
+ defaultStratumId = BASE_STRATUM_NAME;
+ defaultStratumIndex = stratumIndex;
+ createJavaStratum();
+ storeStratum("*terminator*");
+ }
+
+ /***************** query functions ***********************/
+
+ private int stiLineTableIndex(int sti, int jplsLine) {
+ int i;
+ int lineIndexStart;
+ int lineIndexEnd;
+
+ lineIndexStart = stratumTable[sti].lineIndex;
+ /* one past end */
+ lineIndexEnd = stratumTable[sti+1].lineIndex;
+ for (i = lineIndexStart; i < lineIndexEnd; ++i) {
+ if ((jplsLine >= lineTable[i].jplsStart) &&
+ (jplsLine <= lineTable[i].jplsEnd)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int stiLineNumber(int sti, int lti, int jplsLine) {
+ return lineTable[lti].njplsStart +
+ (((jplsLine - lineTable[lti].jplsStart) /
+ lineTable[lti].jplsLineInc));
+ }
+
+ private int fileTableIndex(int sti, int fileId) {
+ int i;
+ int fileIndexStart = stratumTable[sti].fileIndex;
+ /* one past end */
+ int fileIndexEnd = stratumTable[sti+1].fileIndex;
+ for (i = fileIndexStart; i < fileIndexEnd; ++i) {
+ if (fileTable[i].fileId == fileId) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int stiFileTableIndex(int sti, int lti) {
+ return fileTableIndex(sti, lineTable[lti].fileId);
+ }
+
+ boolean isValid() {
+ return isValid;
+ }
+}