jdk/src/share/classes/com/sun/tools/jdi/SDE.java
changeset 2 90ce3da70b43
child 51 6fe31bc95bbc
--- /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;
+    }
+}