jdk/src/share/classes/com/sun/tools/jdi/SDE.java
changeset 2 90ce3da70b43
child 51 6fe31bc95bbc
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package com.sun.tools.jdi;
       
    27 
       
    28 import com.sun.jdi.*;
       
    29 
       
    30 import java.util.*;
       
    31 import java.io.File;
       
    32 
       
    33 class SDE {
       
    34     private static final int INIT_SIZE_FILE = 3;
       
    35     private static final int INIT_SIZE_LINE = 100;
       
    36     private static final int INIT_SIZE_STRATUM = 3;
       
    37 
       
    38     static final String BASE_STRATUM_NAME = "Java";
       
    39 
       
    40     /* for C capatibility */
       
    41     static final String NullString = null;
       
    42 
       
    43     private class FileTableRecord {
       
    44         int fileId;
       
    45         String sourceName;
       
    46         String sourcePath; // do not read - use accessor
       
    47         boolean isConverted = false;
       
    48 
       
    49         /**
       
    50          * Return the sourcePath, computing it if not set.
       
    51          * If set, convert '/' in the sourcePath to the
       
    52          * local file separator.
       
    53          */
       
    54         String getSourcePath(ReferenceTypeImpl refType) {
       
    55             if (!isConverted) {
       
    56                 if (sourcePath == null) {
       
    57                     sourcePath = refType.baseSourceDir() + sourceName;
       
    58                 } else {
       
    59                     StringBuffer buf = new StringBuffer();
       
    60                     for (int i = 0; i < sourcePath.length(); ++i) {
       
    61                         char ch = sourcePath.charAt(i);
       
    62                         if (ch == '/') {
       
    63                             buf.append(File.separatorChar);
       
    64                         } else {
       
    65                             buf.append(ch);
       
    66                         }
       
    67                     }
       
    68                     sourcePath = buf.toString();
       
    69                 }
       
    70                 isConverted = true;
       
    71             }
       
    72             return sourcePath;
       
    73         }
       
    74     }
       
    75 
       
    76     private class LineTableRecord {
       
    77         int jplsStart;
       
    78         int jplsEnd;
       
    79         int jplsLineInc;
       
    80         int njplsStart;
       
    81         int njplsEnd;
       
    82         int fileId;
       
    83     }
       
    84 
       
    85     private class StratumTableRecord {
       
    86         String id;
       
    87         int fileIndex;
       
    88         int lineIndex;
       
    89     }
       
    90 
       
    91     class Stratum {
       
    92         private final int sti; /* stratum index */
       
    93 
       
    94         private Stratum(int sti) {
       
    95             this.sti = sti;
       
    96         }
       
    97 
       
    98         String id() {
       
    99             return stratumTable[sti].id;
       
   100         }
       
   101 
       
   102         boolean isJava() {
       
   103             return sti == baseStratumIndex;
       
   104         }
       
   105 
       
   106         /**
       
   107          * Return all the sourceNames for this stratum.
       
   108          * Look from our starting fileIndex upto the starting
       
   109          * fileIndex of next stratum - can do this since there
       
   110          * is always a terminator stratum.
       
   111          * Default sourceName (the first one) must be first.
       
   112          */
       
   113         List<String> sourceNames(ReferenceTypeImpl refType) {
       
   114             int i;
       
   115             int fileIndexStart = stratumTable[sti].fileIndex;
       
   116             /* one past end */
       
   117             int fileIndexEnd = stratumTable[sti+1].fileIndex;
       
   118             List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
       
   119             for (i = fileIndexStart; i < fileIndexEnd; ++i) {
       
   120                 result.add(fileTable[i].sourceName);
       
   121             }
       
   122             return result;
       
   123         }
       
   124 
       
   125         /**
       
   126          * Return all the sourcePaths for this stratum.
       
   127          * Look from our starting fileIndex upto the starting
       
   128          * fileIndex of next stratum - can do this since there
       
   129          * is always a terminator stratum.
       
   130          * Default sourcePath (the first one) must be first.
       
   131          */
       
   132         List<String> sourcePaths(ReferenceTypeImpl refType) {
       
   133             int i;
       
   134             int fileIndexStart = stratumTable[sti].fileIndex;
       
   135             /* one past end */
       
   136             int fileIndexEnd = stratumTable[sti+1].fileIndex;
       
   137             List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
       
   138             for (i = fileIndexStart; i < fileIndexEnd; ++i) {
       
   139                 result.add(fileTable[i].getSourcePath(refType));
       
   140             }
       
   141             return result;
       
   142         }
       
   143 
       
   144         LineStratum lineStratum(ReferenceTypeImpl refType,
       
   145                                 int jplsLine) {
       
   146             int lti = stiLineTableIndex(sti, jplsLine);
       
   147             if (lti < 0) {
       
   148                 return null;
       
   149             } else {
       
   150                 return new LineStratum(sti, lti, refType,
       
   151                                        jplsLine);
       
   152             }
       
   153         }
       
   154     }
       
   155 
       
   156     class LineStratum {
       
   157         private final int sti; /* stratum index */
       
   158         private final int lti; /* line table index */
       
   159         private final ReferenceTypeImpl refType;
       
   160         private final int jplsLine;
       
   161         private String sourceName = null;
       
   162         private String sourcePath = null;
       
   163 
       
   164         private LineStratum(int sti, int lti,
       
   165                             ReferenceTypeImpl refType,
       
   166                             int jplsLine) {
       
   167             this.sti = sti;
       
   168             this.lti = lti;
       
   169             this.refType = refType;
       
   170             this.jplsLine = jplsLine;
       
   171         }
       
   172 
       
   173         public boolean equals(Object obj) {
       
   174             if ((obj != null) && (obj instanceof LineStratum)) {
       
   175                 LineStratum other = (LineStratum)obj;
       
   176                 return (lti == other.lti) &&
       
   177                        (sti == other.sti) &&
       
   178                        (lineNumber() == other.lineNumber()) &&
       
   179                        (refType.equals(other.refType));
       
   180             } else {
       
   181                 return false;
       
   182             }
       
   183         }
       
   184 
       
   185         int lineNumber() {
       
   186             return stiLineNumber(sti, lti, jplsLine);
       
   187         }
       
   188 
       
   189         /**
       
   190          * Fetch the source name and source path for
       
   191          * this line, converting or constructing
       
   192          * the source path if needed.
       
   193          */
       
   194         void getSourceInfo() {
       
   195             if (sourceName != null) {
       
   196                 // already done
       
   197                 return;
       
   198             }
       
   199             int fti = stiFileTableIndex(sti, lti);
       
   200             if (fti == -1) {
       
   201                 throw new InternalError(
       
   202               "Bad SourceDebugExtension, no matching source id " +
       
   203               lineTable[lti].fileId + " jplsLine: " + jplsLine);
       
   204             }
       
   205             FileTableRecord ftr = fileTable[fti];
       
   206             sourceName = ftr.sourceName;
       
   207             sourcePath = ftr.getSourcePath(refType);
       
   208         }
       
   209 
       
   210         String sourceName() {
       
   211             getSourceInfo();
       
   212             return sourceName;
       
   213         }
       
   214 
       
   215         String sourcePath() {
       
   216             getSourceInfo();
       
   217             return sourcePath;
       
   218         }
       
   219     }
       
   220 
       
   221     private FileTableRecord[] fileTable = null;
       
   222     private LineTableRecord[] lineTable = null;
       
   223     private StratumTableRecord[] stratumTable = null;
       
   224 
       
   225     private int fileIndex = 0;
       
   226     private int lineIndex = 0;
       
   227     private int stratumIndex = 0;
       
   228     private int currentFileId = 0;
       
   229 
       
   230     private int defaultStratumIndex = -1;
       
   231     private int baseStratumIndex = -2; /* so as not to match -1 above */
       
   232     private int sdePos = 0;
       
   233 
       
   234     final String sourceDebugExtension;
       
   235     String jplsFilename = null;
       
   236     String defaultStratumId = null;
       
   237     boolean isValid = false;
       
   238 
       
   239     SDE(String sourceDebugExtension) {
       
   240         this.sourceDebugExtension = sourceDebugExtension;
       
   241         decode();
       
   242     }
       
   243 
       
   244     SDE() {
       
   245         this.sourceDebugExtension = null;
       
   246         createProxyForAbsentSDE();
       
   247     }
       
   248 
       
   249     char sdePeek() {
       
   250         if (sdePos >= sourceDebugExtension.length()) {
       
   251             syntax();
       
   252         }
       
   253         return sourceDebugExtension.charAt(sdePos);
       
   254     }
       
   255 
       
   256     char sdeRead() {
       
   257         if (sdePos >= sourceDebugExtension.length()) {
       
   258             syntax();
       
   259         }
       
   260         return sourceDebugExtension.charAt(sdePos++);
       
   261     }
       
   262 
       
   263     void sdeAdvance() {
       
   264         sdePos++;
       
   265     }
       
   266 
       
   267     void syntax() {
       
   268         throw new InternalError("bad SourceDebugExtension syntax - position " +
       
   269                                 sdePos);
       
   270     }
       
   271 
       
   272     void syntax(String msg) {
       
   273         throw new InternalError("bad SourceDebugExtension syntax: " + msg);
       
   274     }
       
   275 
       
   276     void assureLineTableSize() {
       
   277         int len = lineTable == null? 0 : lineTable.length;
       
   278         if (lineIndex >= len) {
       
   279             int i;
       
   280             int newLen = len == 0? INIT_SIZE_LINE : len * 2;
       
   281             LineTableRecord[] newTable = new LineTableRecord[newLen];
       
   282             for (i = 0; i < len; ++i) {
       
   283                 newTable[i] = lineTable[i];
       
   284             }
       
   285             for (; i < newLen; ++i) {
       
   286                 newTable[i] = new LineTableRecord();
       
   287             }
       
   288             lineTable = newTable;
       
   289         }
       
   290     }
       
   291 
       
   292     void assureFileTableSize() {
       
   293         int len = fileTable == null? 0 : fileTable.length;
       
   294         if (fileIndex >= len) {
       
   295             int i;
       
   296             int newLen = len == 0? INIT_SIZE_FILE : len * 2;
       
   297             FileTableRecord[] newTable = new FileTableRecord[newLen];
       
   298             for (i = 0; i < len; ++i) {
       
   299                 newTable[i] = fileTable[i];
       
   300             }
       
   301             for (; i < newLen; ++i) {
       
   302                 newTable[i] = new FileTableRecord();
       
   303             }
       
   304             fileTable = newTable;
       
   305         }
       
   306     }
       
   307 
       
   308     void assureStratumTableSize() {
       
   309         int len = stratumTable == null? 0 : stratumTable.length;
       
   310         if (stratumIndex >= len) {
       
   311             int i;
       
   312             int newLen = len == 0? INIT_SIZE_STRATUM : len * 2;
       
   313             StratumTableRecord[] newTable = new StratumTableRecord[newLen];
       
   314             for (i = 0; i < len; ++i) {
       
   315                 newTable[i] = stratumTable[i];
       
   316             }
       
   317             for (; i < newLen; ++i) {
       
   318                 newTable[i] = new StratumTableRecord();
       
   319             }
       
   320             stratumTable = newTable;
       
   321         }
       
   322     }
       
   323 
       
   324     String readLine() {
       
   325         StringBuffer sb = new StringBuffer();
       
   326         char ch;
       
   327 
       
   328         ignoreWhite();
       
   329         while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
       
   330             sb.append((char)ch);
       
   331         }
       
   332         // check for CR LF
       
   333         if ((ch == '\r') && (sdePeek() == '\n')) {
       
   334             sdeRead();
       
   335         }
       
   336         ignoreWhite(); // leading white
       
   337         return sb.toString();
       
   338     }
       
   339 
       
   340     private int defaultStratumTableIndex() {
       
   341         if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {
       
   342             defaultStratumIndex =
       
   343                 stratumTableIndex(defaultStratumId);
       
   344         }
       
   345         return defaultStratumIndex;
       
   346     }
       
   347 
       
   348     int stratumTableIndex(String stratumId) {
       
   349         int i;
       
   350 
       
   351         if (stratumId == null) {
       
   352             return defaultStratumTableIndex();
       
   353         }
       
   354         for (i = 0; i < (stratumIndex-1); ++i) {
       
   355             if (stratumTable[i].id.equals(stratumId)) {
       
   356                 return i;
       
   357             }
       
   358         }
       
   359         return defaultStratumTableIndex();
       
   360     }
       
   361 
       
   362     Stratum stratum(String stratumID) {
       
   363         int sti = stratumTableIndex(stratumID);
       
   364         return new Stratum(sti);
       
   365     }
       
   366 
       
   367     List<String> availableStrata() {
       
   368         List<String> strata = new ArrayList<String>();
       
   369 
       
   370         for (int i = 0; i < (stratumIndex-1); ++i) {
       
   371             StratumTableRecord rec = stratumTable[i];
       
   372             strata.add(rec.id);
       
   373         }
       
   374         return strata;
       
   375     }
       
   376 
       
   377 /*****************************
       
   378  * below functions/methods are written to compile under either Java or C
       
   379  *
       
   380  * Needed support functions:
       
   381  *   sdePeek()
       
   382  *   sdeRead()
       
   383  *   sdeAdvance()
       
   384  *   readLine()
       
   385  *   assureLineTableSize()
       
   386  *   assureFileTableSize()
       
   387  *   assureStratumTableSize()
       
   388  *   syntax()
       
   389  *
       
   390  *   stratumTableIndex(String)
       
   391  *
       
   392  * Needed support variables:
       
   393  *   lineTable
       
   394  *   lineIndex
       
   395  *   fileTable
       
   396  *   fileIndex
       
   397  *   currentFileId
       
   398  *
       
   399  * Needed types:
       
   400  *   String
       
   401  *
       
   402  * Needed constants:
       
   403  *   NullString
       
   404  */
       
   405 
       
   406     void ignoreWhite() {
       
   407         char ch;
       
   408 
       
   409         while (((ch = sdePeek()) == ' ') || (ch == '\t')) {
       
   410             sdeAdvance();
       
   411         }
       
   412     }
       
   413 
       
   414     void ignoreLine() {
       
   415         char ch;
       
   416 
       
   417         while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
       
   418         }
       
   419         /* check for CR LF */
       
   420         if ((ch == '\r') && (sdePeek() == '\n')) {
       
   421             sdeAdvance();
       
   422         }
       
   423         ignoreWhite(); /* leading white */
       
   424     }
       
   425 
       
   426     int readNumber() {
       
   427         int value = 0;
       
   428         char ch;
       
   429 
       
   430         ignoreWhite();
       
   431         while (((ch = sdePeek()) >= '0') && (ch <= '9')) {
       
   432             sdeAdvance();
       
   433             value = (value * 10) + ch - '0';
       
   434         }
       
   435         ignoreWhite();
       
   436         return value;
       
   437     }
       
   438 
       
   439     void storeFile(int fileId, String sourceName, String sourcePath) {
       
   440         assureFileTableSize();
       
   441         fileTable[fileIndex].fileId = fileId;
       
   442         fileTable[fileIndex].sourceName = sourceName;
       
   443         fileTable[fileIndex].sourcePath = sourcePath;
       
   444         ++fileIndex;
       
   445     }
       
   446 
       
   447     void fileLine() {
       
   448         int hasAbsolute = 0; /* acts as boolean */
       
   449         int fileId;
       
   450         String sourceName;
       
   451         String sourcePath = null;
       
   452 
       
   453         /* is there an absolute filename? */
       
   454         if (sdePeek() == '+') {
       
   455             sdeAdvance();
       
   456             hasAbsolute = 1;
       
   457         }
       
   458         fileId = readNumber();
       
   459         sourceName = readLine();
       
   460         if (hasAbsolute == 1) {
       
   461             sourcePath = readLine();
       
   462         }
       
   463 
       
   464         storeFile(fileId, sourceName, sourcePath);
       
   465     }
       
   466 
       
   467     void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,
       
   468                   int njplsStart, int njplsEnd, int fileId) {
       
   469         assureLineTableSize();
       
   470         lineTable[lineIndex].jplsStart = jplsStart;
       
   471         lineTable[lineIndex].jplsEnd = jplsEnd;
       
   472         lineTable[lineIndex].jplsLineInc = jplsLineInc;
       
   473         lineTable[lineIndex].njplsStart = njplsStart;
       
   474         lineTable[lineIndex].njplsEnd = njplsEnd;
       
   475         lineTable[lineIndex].fileId = fileId;
       
   476         ++lineIndex;
       
   477     }
       
   478 
       
   479     /**
       
   480      * Parse line translation info.  Syntax is
       
   481      *     <NJ-start-line> [ # <file-id> ] [ , <line-count> ] :
       
   482      *                 <J-start-line> [ , <line-increment> ] CR
       
   483      */
       
   484     void lineLine() {
       
   485         int lineCount = 1;
       
   486         int lineIncrement = 1;
       
   487         int njplsStart;
       
   488         int jplsStart;
       
   489 
       
   490         njplsStart = readNumber();
       
   491 
       
   492         /* is there a fileID? */
       
   493         if (sdePeek() == '#') {
       
   494             sdeAdvance();
       
   495             currentFileId = readNumber();
       
   496         }
       
   497 
       
   498         /* is there a line count? */
       
   499         if (sdePeek() == ',') {
       
   500             sdeAdvance();
       
   501             lineCount = readNumber();
       
   502         }
       
   503 
       
   504         if (sdeRead() != ':') {
       
   505             syntax();
       
   506         }
       
   507         jplsStart = readNumber();
       
   508         if (sdePeek() == ',') {
       
   509             sdeAdvance();
       
   510             lineIncrement = readNumber();
       
   511         }
       
   512         ignoreLine(); /* flush the rest */
       
   513 
       
   514         storeLine(jplsStart,
       
   515                   jplsStart + (lineCount * lineIncrement) -1,
       
   516                   lineIncrement,
       
   517                   njplsStart,
       
   518                   njplsStart + lineCount -1,
       
   519                   currentFileId);
       
   520     }
       
   521 
       
   522     /**
       
   523      * Until the next stratum section, everything after this
       
   524      * is in stratumId - so, store the current indicies.
       
   525      */
       
   526     void storeStratum(String stratumId) {
       
   527         /* remove redundant strata */
       
   528         if (stratumIndex > 0) {
       
   529             if ((stratumTable[stratumIndex-1].fileIndex
       
   530                                             == fileIndex) &&
       
   531                 (stratumTable[stratumIndex-1].lineIndex
       
   532                                             == lineIndex)) {
       
   533                 /* nothing changed overwrite it */
       
   534                 --stratumIndex;
       
   535             }
       
   536         }
       
   537         /* store the results */
       
   538         assureStratumTableSize();
       
   539         stratumTable[stratumIndex].id = stratumId;
       
   540         stratumTable[stratumIndex].fileIndex = fileIndex;
       
   541         stratumTable[stratumIndex].lineIndex = lineIndex;
       
   542         ++stratumIndex;
       
   543         currentFileId = 0;
       
   544     }
       
   545 
       
   546     /**
       
   547      * The beginning of a stratum's info
       
   548      */
       
   549     void stratumSection() {
       
   550         storeStratum(readLine());
       
   551     }
       
   552 
       
   553     void fileSection() {
       
   554         ignoreLine();
       
   555         while (sdePeek() != '*') {
       
   556             fileLine();
       
   557         }
       
   558     }
       
   559 
       
   560     void lineSection() {
       
   561         ignoreLine();
       
   562         while (sdePeek() != '*') {
       
   563             lineLine();
       
   564         }
       
   565     }
       
   566 
       
   567     /**
       
   568      * Ignore a section we don't know about.
       
   569      */
       
   570     void ignoreSection() {
       
   571         ignoreLine();
       
   572         while (sdePeek() != '*') {
       
   573             ignoreLine();
       
   574         }
       
   575     }
       
   576 
       
   577     /**
       
   578      * A base "Java" stratum is always available, though
       
   579      * it is not in the SourceDebugExtension.
       
   580      * Create the base stratum.
       
   581      */
       
   582     void createJavaStratum() {
       
   583         baseStratumIndex = stratumIndex;
       
   584         storeStratum(BASE_STRATUM_NAME);
       
   585         storeFile(1, jplsFilename, NullString);
       
   586         /* JPL line numbers cannot exceed 65535 */
       
   587         storeLine(1, 65536, 1, 1, 65536, 1);
       
   588         storeStratum("Aux"); /* in case they don't declare */
       
   589     }
       
   590 
       
   591     /**
       
   592      * Decode a SourceDebugExtension which is in SourceMap format.
       
   593      * This is the entry point into the recursive descent parser.
       
   594      */
       
   595     void decode() {
       
   596         /* check for "SMAP" - allow EOF if not ours */
       
   597         if ((sourceDebugExtension.length() < 4) ||
       
   598             (sdeRead() != 'S') ||
       
   599             (sdeRead() != 'M') ||
       
   600             (sdeRead() != 'A') ||
       
   601             (sdeRead() != 'P')) {
       
   602             return; /* not our info */
       
   603         }
       
   604         ignoreLine(); /* flush the rest */
       
   605         jplsFilename = readLine();
       
   606         defaultStratumId = readLine();
       
   607         createJavaStratum();
       
   608         while (true) {
       
   609             if (sdeRead() != '*') {
       
   610                 syntax();
       
   611             }
       
   612             switch (sdeRead()) {
       
   613                 case 'S':
       
   614                     stratumSection();
       
   615                     break;
       
   616                 case 'F':
       
   617                     fileSection();
       
   618                     break;
       
   619                 case 'L':
       
   620                     lineSection();
       
   621                     break;
       
   622                 case 'E':
       
   623                     /* set end points */
       
   624                     storeStratum("*terminator*");
       
   625                     isValid = true;
       
   626                     return;
       
   627                 default:
       
   628                     ignoreSection();
       
   629             }
       
   630         }
       
   631     }
       
   632 
       
   633     void createProxyForAbsentSDE() {
       
   634         jplsFilename = null;
       
   635         defaultStratumId = BASE_STRATUM_NAME;
       
   636         defaultStratumIndex = stratumIndex;
       
   637         createJavaStratum();
       
   638         storeStratum("*terminator*");
       
   639     }
       
   640 
       
   641     /***************** query functions ***********************/
       
   642 
       
   643     private int stiLineTableIndex(int sti, int jplsLine) {
       
   644         int i;
       
   645         int lineIndexStart;
       
   646         int lineIndexEnd;
       
   647 
       
   648         lineIndexStart = stratumTable[sti].lineIndex;
       
   649         /* one past end */
       
   650         lineIndexEnd = stratumTable[sti+1].lineIndex;
       
   651         for (i = lineIndexStart; i < lineIndexEnd; ++i) {
       
   652             if ((jplsLine >= lineTable[i].jplsStart) &&
       
   653                             (jplsLine <= lineTable[i].jplsEnd)) {
       
   654                 return i;
       
   655             }
       
   656         }
       
   657         return -1;
       
   658     }
       
   659 
       
   660     private int stiLineNumber(int sti, int lti, int jplsLine) {
       
   661         return lineTable[lti].njplsStart +
       
   662                 (((jplsLine - lineTable[lti].jplsStart) /
       
   663                                    lineTable[lti].jplsLineInc));
       
   664     }
       
   665 
       
   666     private int fileTableIndex(int sti, int fileId) {
       
   667         int i;
       
   668         int fileIndexStart = stratumTable[sti].fileIndex;
       
   669         /* one past end */
       
   670         int fileIndexEnd = stratumTable[sti+1].fileIndex;
       
   671         for (i = fileIndexStart; i < fileIndexEnd; ++i) {
       
   672             if (fileTable[i].fileId == fileId) {
       
   673                 return i;
       
   674             }
       
   675         }
       
   676         return -1;
       
   677     }
       
   678 
       
   679     private int stiFileTableIndex(int sti, int lti) {
       
   680         return fileTableIndex(sti, lineTable[lti].fileId);
       
   681     }
       
   682 
       
   683     boolean isValid() {
       
   684         return isValid;
       
   685     }
       
   686 }