2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package gov.nasa.jpf.util;
24 * support for specification of source locations
26 * This maps sourcefile:line1-range strings into instructions that can be efficiently
27 * checked for by listeners. Example formats are:
29 * X.java (the whole of file X.java)
30 * MyClass.java:42 (file MyClass.java, line1 42)
31 * FooBar.java:42-48 (file FooBar.java, lines 42 to 48)
32 * FooBar.java:42+3 (range of lines from 42 to 45)
33 * x/y/z/whatever:42+ (file with pathname x/y/z/whatever, lines 42 to end)
36 * NOTE path names are given in Unix notation, to avoid the usual Java string
37 * quoting problem with backslashes
39 public class LocationSpec {
41 public static final int ANYLINE = -1;
43 protected StringMatcher pathSpec;
44 protected StringMatcher fileSpec;
45 protected int fromLine = ANYLINE; // inclusive
46 protected int toLine = ANYLINE; // inclusive
49 * factory method that includes the parser
51 public static LocationSpec createLocationSpec (String s){
52 s = s.replace('\\', '/');
54 String pspec = null, fspec;
55 int line1 = -1, line2 = -1;
57 int idx = s.lastIndexOf(':');
58 // check if it is just a dreaded "drive letter"
59 if (idx == s.length()-1 || s.charAt(idx + 1) == '/') {
63 if (idx < 0){ // no line1 spec
66 } else if (idx > 0){ // line1 spec present
67 fspec = s.substring(0, idx).trim();
69 // now get the line1 (range)
70 s = s.substring(idx+1).trim();
75 for (; i < len; i++) {
77 if (c == '-' || c == '+') {
78 line1 = Integer.parseInt(s.substring(0, i));
80 if (i == len - 1) { // open interval
81 line2 = Integer.MAX_VALUE;
83 line2 = Integer.parseInt(s.substring(i + 1));
85 line2 = line1 + line2;
92 if (i == len) { // single line
93 line1 = Integer.parseInt(s);
98 throw new RuntimeException("no filename in LocationSpec: " + s);
101 idx = fspec.lastIndexOf('/');
103 pspec = fspec.substring(0, idx);
104 fspec = fspec.substring(idx+1);
105 } else if (idx == 0){
107 fspec = fspec.substring(1);
112 return new LocationSpec(pspec, fspec, line1, line2);
115 public LocationSpec (String pspec, String fspec, int line1, int line2){
117 pathSpec = new StringMatcher(pspec);
119 fileSpec = new StringMatcher(fspec);
126 public String toString(){
127 StringBuilder sb = new StringBuilder();
129 if (pathSpec != null){
136 if (fromLine != ANYLINE){
140 if (toLine != ANYLINE){
142 if (toLine != Integer.MAX_VALUE){
147 return sb.toString();
150 public boolean matchesFile (File f){
151 if (fileSpec.matches(f.getName())){
152 if (pathSpec != null){
153 String pspec = f.getParent();
154 pspec = pspec.replace('\\', '/'); // use Unix '/' to avoid quoting issue
156 return pathSpec.matches(pspec);
166 public boolean isAnyLine(){
167 return fromLine == ANYLINE;
170 public boolean isLineInterval(){
171 return toLine != ANYLINE;
174 public int getLine(){ // for specs that are single locations
178 public int getFromLine() {
182 // note - this is < 0 if there was only a
183 public int getToLine() {
194 * 'pathName' has to use '/' as separators
196 public boolean matchesFile (String pathName){
197 if (pathName != null){
198 pathName = pathName.replace('\\', '/');
199 int idx = pathName.lastIndexOf('/');
202 String fname = pathName.substring(idx + 1);
204 if (fileSpec.matches(fname)) {
205 if (pathSpec != null) {
206 String pname = idx > 0 ? pathName.substring(0, idx) : "/";
207 return pathSpec.matches(pname);
214 return fileSpec.matches(pathName);
221 public boolean includesLine (int line){
222 if (fromLine == ANYLINE){
226 if (fromLine == line){
228 } else if (fromLine < line){
229 if (toLine == ANYLINE){ // single location
232 return (line <= toLine);