|
Added
Link Here
|
| 1 |
/******************************************************************************* |
| 2 |
* Copyright (c) 2004, 2009 IBM Corporation and others. |
| 3 |
* All rights reserved. This program and the accompanying materials |
| 4 |
* are made available under the terms of the Eclipse Public License v1.0 |
| 5 |
* which accompanies this distribution, and is available at |
| 6 |
* http://www.eclipse.org/legal/epl-v10.html |
| 7 |
* |
| 8 |
* Contributors: |
| 9 |
* IBM - Initial API and implementation |
| 10 |
*******************************************************************************/ |
| 11 |
package org.eclipse.cdt.make.xlc.core.scannerconfig; |
| 12 |
|
| 13 |
import java.io.File; |
| 14 |
import java.io.IOException; |
| 15 |
import java.net.URI; |
| 16 |
import java.net.URISyntaxException; |
| 17 |
import java.util.ArrayList; |
| 18 |
import java.util.HashMap; |
| 19 |
import java.util.Iterator; |
| 20 |
import java.util.List; |
| 21 |
import java.util.Map; |
| 22 |
import java.util.Vector; |
| 23 |
|
| 24 |
import org.eclipse.cdt.core.IMarkerGenerator; |
| 25 |
import org.eclipse.cdt.core.ProblemMarkerInfo; |
| 26 |
import org.eclipse.cdt.make.core.MakeCorePlugin; |
| 27 |
import org.eclipse.cdt.make.internal.core.MakeMessages; |
| 28 |
import org.eclipse.cdt.make.internal.core.scannerconfig.util.CCommandDSC; |
| 29 |
import org.eclipse.cdt.make.internal.core.scannerconfig.util.KVStringPair; |
| 30 |
import org.eclipse.cdt.make.internal.core.scannerconfig.util.SCDOptionsEnum; |
| 31 |
import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; |
| 32 |
import org.eclipse.cdt.utils.FileSystemUtilityManager; |
| 33 |
import org.eclipse.core.resources.IContainer; |
| 34 |
import org.eclipse.core.resources.IFile; |
| 35 |
import org.eclipse.core.resources.IProject; |
| 36 |
import org.eclipse.core.resources.IResource; |
| 37 |
import org.eclipse.core.resources.IWorkspaceRoot; |
| 38 |
import org.eclipse.core.runtime.CoreException; |
| 39 |
import org.eclipse.core.runtime.IPath; |
| 40 |
import org.eclipse.core.runtime.Path; |
| 41 |
|
| 42 |
/** |
| 43 |
* @author crecoskie |
| 44 |
* |
| 45 |
*/ |
| 46 |
public class XLCBuildOutputParserUtility { |
| 47 |
protected class Problem { |
| 48 |
protected String description; |
| 49 |
protected IResource file; |
| 50 |
protected int lineNumber; |
| 51 |
protected int severity; |
| 52 |
protected String variableName; |
| 53 |
|
| 54 |
public Problem(IResource file, int lineNumber, String desciption, int severity, String variableName) { |
| 55 |
this.file = file; |
| 56 |
this.lineNumber = lineNumber; |
| 57 |
this.description = desciption; |
| 58 |
this.severity = severity; |
| 59 |
this.variableName = variableName; |
| 60 |
} |
| 61 |
} |
| 62 |
public static IPath convertCygpath(IPath path) { |
| 63 |
if (path.segmentCount() > 1 && path.segment(0).equals("cygdrive")) { //$NON-NLS-1$ |
| 64 |
StringBuffer buf = new StringBuffer(2); |
| 65 |
buf.append(Character.toUpperCase(path.segment(1).charAt(0))); |
| 66 |
buf.append(':'); |
| 67 |
path = path.removeFirstSegments(2); |
| 68 |
path = path.setDevice(buf.toString()); |
| 69 |
path = path.makeAbsolute(); |
| 70 |
} |
| 71 |
return path; |
| 72 |
} |
| 73 |
private List commandsList2; |
| 74 |
private int commandsN = 0; |
| 75 |
private List compiledFileList; |
| 76 |
|
| 77 |
private Map directoryCommandListMap; |
| 78 |
|
| 79 |
private IPath fBaseDirectory; |
| 80 |
private String fDefaultMacroDefinitionValue= "1"; //$NON-NLS-1$ |
| 81 |
private Vector<IPath> fDirectoryStack; |
| 82 |
private ArrayList<Problem> fErrors; |
| 83 |
private int filesN = 0; |
| 84 |
|
| 85 |
private IMarkerGenerator fMarkerGenerator; |
| 86 |
|
| 87 |
private IProject project; |
| 88 |
|
| 89 |
private int workingDirsN = 0; |
| 90 |
|
| 91 |
/* |
| 92 |
* For tracking the location of files being compiled |
| 93 |
*/ |
| 94 |
private Map<String, IFile> fFilesInProject; |
| 95 |
private List<String> fCollectedFiles; |
| 96 |
private List<String> fNameConflicts; |
| 97 |
|
| 98 |
/** |
| 99 |
* |
| 100 |
*/ |
| 101 |
public XLCBuildOutputParserUtility(IProject project, IPath workingDirectory, |
| 102 |
IMarkerGenerator markerGenerator) { |
| 103 |
fDirectoryStack = new Vector<IPath>(); |
| 104 |
fErrors = new ArrayList<Problem>(); |
| 105 |
this.project = project; |
| 106 |
fBaseDirectory = getPathForResource(project); |
| 107 |
if (workingDirectory != null) { |
| 108 |
pushDirectory(workingDirectory); |
| 109 |
} |
| 110 |
} |
| 111 |
|
| 112 |
private IPath getPathForResource(IResource resource) { |
| 113 |
// TODO: when the file system utility stuff is in, this will have to call it to get the path |
| 114 |
// for now, get the path from the URI |
| 115 |
URI locationURI = resource.getLocationURI(); |
| 116 |
IPath path = new Path(locationURI.getPath()); |
| 117 |
return path; |
| 118 |
} |
| 119 |
|
| 120 |
/** |
| 121 |
* Adds a mapping filename, generic_command |
| 122 |
* @param longFileName |
| 123 |
* @param genericLine |
| 124 |
*/ |
| 125 |
void addGenericCommandForFile(String longFileName, String genericCommand) { |
| 126 |
// if a file name has already been added once, return |
| 127 |
if (compiledFileList.contains(longFileName)) |
| 128 |
return; |
| 129 |
compiledFileList.add(longFileName); |
| 130 |
|
| 131 |
String workingDir = getWorkingDirectory().toString(); |
| 132 |
List directoryCommandList = (List) directoryCommandListMap.get(workingDir); |
| 133 |
if (directoryCommandList == null) { |
| 134 |
directoryCommandList = new ArrayList(); |
| 135 |
directoryCommandListMap.put(workingDir, directoryCommandList); |
| 136 |
++workingDirsN; |
| 137 |
} |
| 138 |
Map command21FileListMap = null; |
| 139 |
for (Iterator i = directoryCommandList.iterator(); i.hasNext(); ) { |
| 140 |
command21FileListMap = (Map) i.next(); |
| 141 |
List fileList = (List) command21FileListMap.get(genericCommand); |
| 142 |
if (fileList != null) { |
| 143 |
if (!fileList.contains(longFileName)) { |
| 144 |
fileList.add(longFileName); |
| 145 |
++filesN; |
| 146 |
} |
| 147 |
return; |
| 148 |
} |
| 149 |
} |
| 150 |
command21FileListMap = new HashMap(1); |
| 151 |
directoryCommandList.add(command21FileListMap); |
| 152 |
++commandsN; |
| 153 |
List fileList = new ArrayList(); |
| 154 |
command21FileListMap.put(genericCommand, fileList); |
| 155 |
fileList.add(longFileName); |
| 156 |
++filesN; |
| 157 |
} |
| 158 |
|
| 159 |
/** |
| 160 |
* Adds a mapping command line -> file, this time without a dir |
| 161 |
* @param longFileName |
| 162 |
* @param genericLine |
| 163 |
*/ |
| 164 |
void addGenericCommandForFile2(String longFileName, String genericLine) { |
| 165 |
// if a file name has already been added once, return |
| 166 |
if (compiledFileList.contains(longFileName)) |
| 167 |
return; |
| 168 |
compiledFileList.add(longFileName); |
| 169 |
|
| 170 |
String[] tokens = genericLine.split("\\s+"); //$NON-NLS-1$ |
| 171 |
CCommandDSC command = getNewCCommandDSC(tokens, 0, false); // assume .c file type |
| 172 |
int index = commandsList2.indexOf(command); |
| 173 |
if (index == -1) { |
| 174 |
commandsList2.add(command); |
| 175 |
++commandsN; |
| 176 |
} |
| 177 |
else { |
| 178 |
command = (CCommandDSC) commandsList2.get(index); |
| 179 |
} |
| 180 |
// // add a file |
| 181 |
// command.addFile(longFileName); |
| 182 |
// ++filesN; |
| 183 |
} |
| 184 |
|
| 185 |
public void changeMakeDirectory(String dir, int dirLevel, boolean enterDir) { |
| 186 |
if (enterDir) { |
| 187 |
/* Sometimes make screws up the output, so |
| 188 |
* "leave" events can't be seen. Double-check level |
| 189 |
* here. |
| 190 |
*/ |
| 191 |
for (int parseLevel = getDirectoryLevel(); dirLevel < parseLevel; parseLevel = getDirectoryLevel()) { |
| 192 |
popDirectory(); |
| 193 |
} |
| 194 |
pushDirectory(new Path(dir)); |
| 195 |
} else { |
| 196 |
popDirectory(); |
| 197 |
/* Could check to see if they match */ |
| 198 |
} |
| 199 |
} |
| 200 |
|
| 201 |
/** |
| 202 |
* Called by the console line parsers to generate a problem marker. |
| 203 |
*/ |
| 204 |
public void generateMarker(IResource file, int lineNumber, String desc, int severity, String varName) { |
| 205 |
// No need to collect markers if marker generator is not present |
| 206 |
if (fMarkerGenerator != null) { |
| 207 |
Problem problem = new Problem(file, lineNumber, desc, severity, varName); |
| 208 |
fErrors.add(problem); |
| 209 |
} |
| 210 |
} |
| 211 |
|
| 212 |
/** |
| 213 |
* |
| 214 |
*/ |
| 215 |
void generateReport() { |
| 216 |
TraceUtil.metricsTrace("Stats for directory ", //$NON-NLS-1$ |
| 217 |
"Generic command: '", "' applicable for:", //$NON-NLS-1$ //$NON-NLS-2$ |
| 218 |
directoryCommandListMap); |
| 219 |
TraceUtil.summaryTrace("Discovery summary", workingDirsN, commandsN, filesN); //$NON-NLS-1$ |
| 220 |
} |
| 221 |
|
| 222 |
/** |
| 223 |
* @param filePath : String |
| 224 |
* @return filePath : IPath - not <code>null</code> |
| 225 |
*/ |
| 226 |
public IPath getAbsolutePath(String filePath) { |
| 227 |
IPath pFilePath; |
| 228 |
if (filePath.startsWith("/")) { //$NON-NLS-1$ |
| 229 |
return convertCygpath(new Path(filePath)); |
| 230 |
} |
| 231 |
else if (filePath.startsWith("\\") || //$NON-NLS-1$ |
| 232 |
(!filePath.startsWith(".") && //$NON-NLS-1$ |
| 233 |
filePath.length() > 2 && filePath.charAt(1) == ':' && |
| 234 |
(filePath.charAt(2) == '\\' || filePath.charAt(2) == '/'))) { |
| 235 |
// absolute path |
| 236 |
pFilePath = new Path(filePath); |
| 237 |
} |
| 238 |
else { |
| 239 |
// relative path |
| 240 |
IPath cwd = getWorkingDirectory(); |
| 241 |
if (!cwd.isAbsolute()) { |
| 242 |
cwd = getBaseDirectory().append(cwd); |
| 243 |
} |
| 244 |
if (filePath.startsWith("`pwd`")) { //$NON-NLS-1$ |
| 245 |
if (filePath.length() > 5 && (filePath.charAt(5) == '/' || filePath.charAt(5) == '\\')) { |
| 246 |
filePath = filePath.substring(6); |
| 247 |
} |
| 248 |
else { |
| 249 |
filePath = filePath.substring(5); |
| 250 |
} |
| 251 |
} |
| 252 |
pFilePath = cwd.append(filePath); |
| 253 |
} |
| 254 |
return pFilePath; |
| 255 |
} |
| 256 |
/** |
| 257 |
* @return Returns the fBaseDirectory. |
| 258 |
*/ |
| 259 |
public IPath getBaseDirectory() { |
| 260 |
return fBaseDirectory; |
| 261 |
} |
| 262 |
|
| 263 |
/** |
| 264 |
* Returns all CCommandDSC collected so far. |
| 265 |
* Currently this list is not filled, so it will always return an empty list. |
| 266 |
* @return List of CCommandDSC |
| 267 |
*/ |
| 268 |
public List getCCommandDSCList() { |
| 269 |
return new ArrayList(commandsList2); |
| 270 |
} |
| 271 |
|
| 272 |
protected int getDirectoryLevel() { |
| 273 |
return fDirectoryStack.size(); |
| 274 |
} |
| 275 |
/** |
| 276 |
* @return Returns the fDirectoryStack. |
| 277 |
*/ |
| 278 |
protected Vector<IPath> getDirectoryStack() { |
| 279 |
return fDirectoryStack; |
| 280 |
} |
| 281 |
/** |
| 282 |
* @return Returns the fErrors. |
| 283 |
*/ |
| 284 |
protected ArrayList<Problem> getErrors() { |
| 285 |
return fErrors; |
| 286 |
} |
| 287 |
/** |
| 288 |
* @return Returns the fMarkerGenerator. |
| 289 |
*/ |
| 290 |
protected IMarkerGenerator getMarkerGenerator() { |
| 291 |
return fMarkerGenerator; |
| 292 |
} |
| 293 |
|
| 294 |
/** |
| 295 |
* @param genericLine |
| 296 |
* @param cppFileType |
| 297 |
* @return CCommandDSC compile command description |
| 298 |
*/ |
| 299 |
public CCommandDSC getNewCCommandDSC(String[] tokens, final int idxOfCompilerCommand, boolean cppFileType) { |
| 300 |
ArrayList dirafter = new ArrayList(); |
| 301 |
ArrayList includes = new ArrayList(); |
| 302 |
CCommandDSC command = new CCommandDSC(cppFileType, getProject()); |
| 303 |
command.addSCOption(new KVStringPair(SCDOptionsEnum.COMMAND.toString(), tokens[idxOfCompilerCommand])); |
| 304 |
for (int i = idxOfCompilerCommand+1; i < tokens.length; ++i) { |
| 305 |
String token = tokens[i]; |
| 306 |
//Target specific options: see GccScannerInfoConsoleParser |
| 307 |
if (token.startsWith("-m") || //$NON-NLS-1$ |
| 308 |
token.equals("-ansi") || //$NON-NLS-1$ |
| 309 |
token.equals("-posix") || //$NON-NLS-1$ |
| 310 |
token.equals("-pthread") || //$NON-NLS-1$ |
| 311 |
token.startsWith("-O") || //$NON-NLS-1$ |
| 312 |
token.equals("-fno-inline") || //$NON-NLS-1$ |
| 313 |
token.startsWith("-finline") || //$NON-NLS-1$ |
| 314 |
token.equals("-fno-exceptions") || //$NON-NLS-1$ |
| 315 |
token.equals("-fexceptions") || //$NON-NLS-1$ |
| 316 |
token.equals("-fshort-wchar") || //$NON-NLS-1$ |
| 317 |
token.equals("-fshort-double") || //$NON-NLS-1$ |
| 318 |
token.equals("-fno-signed-char") || //$NON-NLS-1$ |
| 319 |
token.equals("-fsigned-char") || //$NON-NLS-1$ |
| 320 |
token.startsWith("-fabi-version=") //$NON-NLS-1$ |
| 321 |
) { |
| 322 |
command.addSCOption(new KVStringPair(SCDOptionsEnum.COMMAND.toString(), token)); |
| 323 |
continue; |
| 324 |
} |
| 325 |
for (int j = SCDOptionsEnum.MIN; j <= SCDOptionsEnum.MAX; ++j) { |
| 326 |
final SCDOptionsEnum optionKind = SCDOptionsEnum.getSCDOptionsEnum(j); |
| 327 |
if (token.startsWith(optionKind.toString())) { |
| 328 |
String option = token.substring( |
| 329 |
optionKind.toString().length()).trim(); |
| 330 |
if (option.length() > 0) { |
| 331 |
// ex. -I/dir |
| 332 |
} |
| 333 |
else if (optionKind.equals(SCDOptionsEnum.IDASH)) { |
| 334 |
for (Iterator iter=includes.iterator(); iter.hasNext(); ) { |
| 335 |
option = (String)iter.next(); |
| 336 |
KVStringPair pair = new KVStringPair(SCDOptionsEnum.IQUOTE.toString(), option); |
| 337 |
command.addSCOption(pair); |
| 338 |
} |
| 339 |
includes = new ArrayList(); |
| 340 |
// -I- has no parameter |
| 341 |
} |
| 342 |
else { |
| 343 |
// ex. -I /dir |
| 344 |
// take a next token |
| 345 |
if (i+1 < tokens.length && !tokens[i+1].startsWith("-")) { //$NON-NLS-1$ |
| 346 |
option = tokens[++i]; |
| 347 |
} |
| 348 |
else break; |
| 349 |
} |
| 350 |
|
| 351 |
if (option.length() > 0 && ( |
| 352 |
optionKind.equals(SCDOptionsEnum.INCLUDE) || |
| 353 |
optionKind.equals(SCDOptionsEnum.INCLUDE_FILE) || |
| 354 |
optionKind.equals(SCDOptionsEnum.IMACROS_FILE) || |
| 355 |
optionKind.equals(SCDOptionsEnum.IDIRAFTER) || |
| 356 |
optionKind.equals(SCDOptionsEnum.ISYSTEM) || |
| 357 |
optionKind.equals(SCDOptionsEnum.IQUOTE) )) { |
| 358 |
option = (getAbsolutePath(option)).toString(); |
| 359 |
} |
| 360 |
|
| 361 |
if (optionKind.equals(SCDOptionsEnum.IDIRAFTER)) { |
| 362 |
KVStringPair pair = new KVStringPair(SCDOptionsEnum.INCLUDE.toString(), option); |
| 363 |
dirafter.add(pair); |
| 364 |
} |
| 365 |
else if (optionKind.equals(SCDOptionsEnum.INCLUDE)) { |
| 366 |
includes.add(option); |
| 367 |
} |
| 368 |
else { // add the pair |
| 369 |
if (optionKind.equals(SCDOptionsEnum.DEFINE)) { |
| 370 |
if (option.indexOf('=') == -1) { |
| 371 |
option += '='+ fDefaultMacroDefinitionValue; |
| 372 |
} |
| 373 |
} |
| 374 |
KVStringPair pair = new KVStringPair(optionKind.toString(), option); |
| 375 |
command.addSCOption(pair); |
| 376 |
} |
| 377 |
break; |
| 378 |
} |
| 379 |
} |
| 380 |
} |
| 381 |
String option; |
| 382 |
for (Iterator iter=includes.iterator(); iter.hasNext(); ) { |
| 383 |
option = (String)iter.next(); |
| 384 |
KVStringPair pair = new KVStringPair(SCDOptionsEnum.INCLUDE.toString(), option); |
| 385 |
command.addSCOption(pair); |
| 386 |
} |
| 387 |
for (Iterator iter=dirafter.iterator(); iter.hasNext(); ) { |
| 388 |
command.addSCOption((KVStringPair)iter.next()); |
| 389 |
} |
| 390 |
return command; |
| 391 |
} |
| 392 |
|
| 393 |
/** |
| 394 |
* @return Returns the project. |
| 395 |
*/ |
| 396 |
protected IProject getProject() { |
| 397 |
return project; |
| 398 |
} |
| 399 |
|
| 400 |
public IPath getWorkingDirectory() { |
| 401 |
if (fDirectoryStack.size() != 0) { |
| 402 |
return fDirectoryStack.lastElement(); |
| 403 |
} |
| 404 |
// Fallback to the Project Location |
| 405 |
// FIXME: if the build did not start in the Project ? |
| 406 |
return fBaseDirectory; |
| 407 |
} |
| 408 |
|
| 409 |
protected IPath popDirectory() { |
| 410 |
int i = getDirectoryLevel(); |
| 411 |
if (i != 0) { |
| 412 |
IPath dir = fDirectoryStack.lastElement(); |
| 413 |
fDirectoryStack.removeElementAt(i - 1); |
| 414 |
return dir; |
| 415 |
} |
| 416 |
return new Path(""); //$NON-NLS-1$ |
| 417 |
} |
| 418 |
|
| 419 |
protected void pushDirectory(IPath dir) { |
| 420 |
if (dir != null) { |
| 421 |
IPath pwd = null; |
| 422 |
if (fBaseDirectory != null && fBaseDirectory.isPrefixOf(dir)) { |
| 423 |
pwd = dir.removeFirstSegments(fBaseDirectory.segmentCount()); |
| 424 |
} else { |
| 425 |
// check if it is a cygpath |
| 426 |
pwd= convertCygpath(dir); |
| 427 |
} |
| 428 |
fDirectoryStack.addElement(pwd); |
| 429 |
} |
| 430 |
} |
| 431 |
|
| 432 |
public boolean reportProblems() { |
| 433 |
boolean reset = false; |
| 434 |
for (Iterator<Problem> iter = fErrors.iterator(); iter.hasNext(); ) { |
| 435 |
Problem problem = iter.next(); |
| 436 |
if (problem.severity == IMarkerGenerator.SEVERITY_ERROR_BUILD) { |
| 437 |
reset = true; |
| 438 |
} |
| 439 |
if (problem.file == null) { |
| 440 |
fMarkerGenerator.addMarker(new ProblemMarkerInfo( |
| 441 |
project, |
| 442 |
problem.lineNumber, |
| 443 |
problem.description, |
| 444 |
problem.severity, |
| 445 |
problem.variableName)); |
| 446 |
} else { |
| 447 |
fMarkerGenerator.addMarker(new ProblemMarkerInfo( |
| 448 |
problem.file, |
| 449 |
problem.lineNumber, |
| 450 |
problem.description, |
| 451 |
problem.severity, |
| 452 |
problem.variableName)); |
| 453 |
} |
| 454 |
} |
| 455 |
fErrors.clear(); |
| 456 |
return reset; |
| 457 |
} |
| 458 |
|
| 459 |
public void setDefaultMacroDefinitionValue(String val) { |
| 460 |
if (val != null) { |
| 461 |
fDefaultMacroDefinitionValue= val; |
| 462 |
} |
| 463 |
} |
| 464 |
|
| 465 |
public String getDefaultMacroDefinitionValue() { |
| 466 |
return fDefaultMacroDefinitionValue; |
| 467 |
} |
| 468 |
|
| 469 |
public String normalizePath(String path) { |
| 470 |
int column = path.indexOf(':'); |
| 471 |
if (column > 0) { |
| 472 |
char driveLetter = path.charAt(column - 1); |
| 473 |
if (Character.isLowerCase(driveLetter)) { |
| 474 |
StringBuffer sb = new StringBuffer(); |
| 475 |
if (column - 1 > 0) { |
| 476 |
sb.append(path.substring(0, column-1)); |
| 477 |
} |
| 478 |
sb.append(Character.toUpperCase(driveLetter)); |
| 479 |
sb.append(path.substring(column)); |
| 480 |
path = sb.toString(); |
| 481 |
} |
| 482 |
} |
| 483 |
if (path.indexOf('.') == -1 || path.equals(".")) { //$NON-NLS-1$ |
| 484 |
return (new Path(path)).toString(); // convert separators to '/' |
| 485 |
} |
| 486 |
// lose "./" segments since they confuse the Path normalization |
| 487 |
StringBuffer buf = new StringBuffer(path); |
| 488 |
int len = buf.length(); |
| 489 |
StringBuffer newBuf = new StringBuffer(buf.length()); |
| 490 |
int scp = 0; // starting copy point |
| 491 |
int ssp = 0; // starting search point |
| 492 |
int sdot; |
| 493 |
boolean validPrefix; |
| 494 |
while (ssp < len && (sdot = buf.indexOf(".", ssp)) != -1) { //$NON-NLS-1$ |
| 495 |
validPrefix = false; |
| 496 |
int ddot = buf.indexOf("..", ssp);//$NON-NLS-1$ |
| 497 |
if (sdot < ddot || ddot == -1) { |
| 498 |
newBuf.append(buf.substring(scp, sdot)); |
| 499 |
scp = sdot; |
| 500 |
ssp = sdot + 1; |
| 501 |
if (ssp < len) { |
| 502 |
if (sdot == 0 || buf.charAt(sdot - 1) == '/' || buf.charAt(sdot - 1) == '\\') { |
| 503 |
validPrefix = true; |
| 504 |
} |
| 505 |
char nextChar = buf.charAt(ssp); |
| 506 |
if (validPrefix && nextChar == '/') { |
| 507 |
++ssp; |
| 508 |
scp = ssp; |
| 509 |
} |
| 510 |
else if (validPrefix && nextChar == '\\') { |
| 511 |
++ssp; |
| 512 |
if (ssp < len - 1 && buf.charAt(ssp) == '\\') { |
| 513 |
++ssp; |
| 514 |
} |
| 515 |
scp = ssp; |
| 516 |
} |
| 517 |
else { |
| 518 |
// no path delimiter, must be '.' inside the path |
| 519 |
scp = ssp - 1; |
| 520 |
} |
| 521 |
} |
| 522 |
} |
| 523 |
else if (sdot == ddot) { |
| 524 |
ssp = sdot + 2; |
| 525 |
} |
| 526 |
} |
| 527 |
newBuf.append(buf.substring(scp, len)); |
| 528 |
|
| 529 |
IPath orgPath = new Path(newBuf.toString()); |
| 530 |
return orgPath.toString(); |
| 531 |
} |
| 532 |
|
| 533 |
|
| 534 |
/** |
| 535 |
* Called by the console line parsers to find a file with a given name. |
| 536 |
* @param fileName |
| 537 |
* @return IFile or null |
| 538 |
*/ |
| 539 |
public IFile findFile(String fileName) { |
| 540 |
IFile file = findFilePath(fileName); |
| 541 |
if (file == null) { |
| 542 |
// Try the project's map. |
| 543 |
file = findFileName(fileName); |
| 544 |
if (file != null) { |
| 545 |
// If there is a conflict then try all files in the project. |
| 546 |
if (isConflictingName(fileName)) { |
| 547 |
file = null; |
| 548 |
|
| 549 |
// Create a problem marker |
| 550 |
final String error = MakeMessages.getString("ConsoleParser.Ambiguous_Filepath_Error_Message"); //$NON-NLS-1$ |
| 551 |
TraceUtil.outputError(error, fileName); |
| 552 |
generateMarker(getProject(), -1, error+fileName, IMarkerGenerator.SEVERITY_WARNING, null); |
| 553 |
} |
| 554 |
} |
| 555 |
} |
| 556 |
return file; |
| 557 |
} |
| 558 |
|
| 559 |
/** |
| 560 |
* @param filePath |
| 561 |
* @return |
| 562 |
*/ |
| 563 |
protected IFile findFilePath(String filePath) { |
| 564 |
IPath path = null; |
| 565 |
IPath fp = new Path(filePath); |
| 566 |
if (fp.isAbsolute()) { |
| 567 |
if (getBaseDirectory().isPrefixOf(fp)) { |
| 568 |
int segments = getBaseDirectory().matchingFirstSegments(fp); |
| 569 |
path = fp.removeFirstSegments(segments); |
| 570 |
} else { |
| 571 |
path = fp; |
| 572 |
} |
| 573 |
} else { |
| 574 |
path = getWorkingDirectory().append(filePath); |
| 575 |
} |
| 576 |
|
| 577 |
IFile file = null; |
| 578 |
// The workspace may throw an IllegalArgumentException |
| 579 |
// Catch it and the parser should fallback to scan the entire project. |
| 580 |
try { |
| 581 |
file = findFileInWorkspace(path); |
| 582 |
} catch (Exception e) { |
| 583 |
} |
| 584 |
|
| 585 |
// We have to do another try, on Windows for cases like "TEST.C" vs "test.c" |
| 586 |
// We use the java.io.File canonical path. |
| 587 |
if (file == null || !file.exists()) { |
| 588 |
File f = path.toFile(); |
| 589 |
try { |
| 590 |
String canon = f.getCanonicalPath(); |
| 591 |
path = new Path(canon); |
| 592 |
file = findFileInWorkspace(path); |
| 593 |
} catch (IOException e1) { |
| 594 |
} |
| 595 |
} |
| 596 |
return (file != null && file.exists()) ? file : null; |
| 597 |
} |
| 598 |
|
| 599 |
/** |
| 600 |
* @param fileName |
| 601 |
* @return |
| 602 |
*/ |
| 603 |
protected IFile findFileName(String fileName) { |
| 604 |
IPath path = new Path(fileName); |
| 605 |
return (IFile) fFilesInProject.get(path.lastSegment()); |
| 606 |
} |
| 607 |
|
| 608 |
protected IFile findFileInWorkspace(IPath path) { |
| 609 |
IFile file = null; |
| 610 |
if (path.isAbsolute()) { |
| 611 |
IWorkspaceRoot root = getProject().getWorkspace().getRoot(); |
| 612 |
|
| 613 |
// construct a URI, based on the project's locationURI, that points |
| 614 |
// to the given path |
| 615 |
URI projectURI = project.getLocationURI(); |
| 616 |
|
| 617 |
URI newURI = FileSystemUtilityManager.getDefault().replacePath(projectURI, path.toString()); |
| 618 |
|
| 619 |
IFile[] files = root.findFilesForLocationURI(newURI); |
| 620 |
|
| 621 |
for (int i = 0; i < files.length; i++) { |
| 622 |
if (files[i].getProject().equals(getProject())) { |
| 623 |
file = files[i]; |
| 624 |
break; |
| 625 |
} |
| 626 |
} |
| 627 |
|
| 628 |
} else { |
| 629 |
file = getProject().getFile(path); |
| 630 |
} |
| 631 |
return file; |
| 632 |
} |
| 633 |
|
| 634 |
protected void collectFiles(IContainer parent, List result) { |
| 635 |
try { |
| 636 |
IResource[] resources = parent.members(); |
| 637 |
for (int i = 0; i < resources.length; i++) { |
| 638 |
IResource resource = resources[i]; |
| 639 |
if (resource instanceof IFile) { |
| 640 |
result.add(resource); |
| 641 |
} else if (resource instanceof IContainer) { |
| 642 |
collectFiles((IContainer) resource, result); |
| 643 |
} |
| 644 |
} |
| 645 |
} catch (CoreException e) { |
| 646 |
MakeCorePlugin.log(e.getStatus()); |
| 647 |
} |
| 648 |
} |
| 649 |
|
| 650 |
protected boolean isConflictingName(String fileName) { |
| 651 |
IPath path = new Path(fileName); |
| 652 |
return fNameConflicts.contains(path.lastSegment()); |
| 653 |
} |
| 654 |
|
| 655 |
public List translateRelativePaths(IFile file, String fileName, List includes) { |
| 656 |
List translatedIncludes = new ArrayList(includes.size()); |
| 657 |
for (Iterator i = includes.iterator(); i.hasNext(); ) { |
| 658 |
String include = (String) i.next(); |
| 659 |
IPath includePath = new Path(include); |
| 660 |
if (!includePath.isAbsolute() && !includePath.isUNC()) { // do not translate UNC paths |
| 661 |
// First try the current working directory |
| 662 |
IPath cwd = getWorkingDirectory(); |
| 663 |
if (!cwd.isAbsolute()) { |
| 664 |
cwd = getBaseDirectory().append(cwd); |
| 665 |
} |
| 666 |
|
| 667 |
IPath filePath = new Path(fileName); |
| 668 |
if (!filePath.isAbsolute()) { |
| 669 |
// check if the cwd is the right one |
| 670 |
// appending fileName to cwd should yield file path |
| 671 |
filePath = cwd.append(fileName); |
| 672 |
} |
| 673 |
if (!filePath.toString().equalsIgnoreCase(file.getLocation().toString())) { |
| 674 |
// must be the cwd is wrong |
| 675 |
// check if file name starts with ".." |
| 676 |
if (fileName.startsWith("..")) { //$NON-NLS-1$ |
| 677 |
// probably multiple choices for cwd, hopeless |
| 678 |
final String error = MakeMessages.getString("ConsoleParser.Working_Directory_Error_Message"); //$NON-NLS-1$ |
| 679 |
TraceUtil.outputError(error, fileName); |
| 680 |
generateMarker(file, -1, error, IMarkerGenerator.SEVERITY_WARNING, fileName); |
| 681 |
break; |
| 682 |
} |
| 683 |
else { |
| 684 |
// remove common segments at the end |
| 685 |
IPath tPath = new Path(fileName); |
| 686 |
if (fileName.startsWith(".")) { //$NON-NLS-1$ |
| 687 |
tPath = tPath.removeFirstSegments(1); |
| 688 |
} |
| 689 |
// get the file path from the file |
| 690 |
filePath = file.getLocation(); |
| 691 |
IPath lastFileSegment = filePath.removeFirstSegments(filePath.segmentCount() - tPath.segmentCount()); |
| 692 |
if (lastFileSegment.matchingFirstSegments(tPath) == tPath.segmentCount()) { |
| 693 |
cwd = filePath.removeLastSegments(tPath.segmentCount()); |
| 694 |
} |
| 695 |
} |
| 696 |
} |
| 697 |
|
| 698 |
IPath candidatePath = cwd.append(includePath); |
| 699 |
File dir = candidatePath.toFile(); |
| 700 |
include = candidatePath.toString(); |
| 701 |
if (!dir.exists()) { |
| 702 |
final String error = MakeMessages.getString("ConsoleParser.Nonexistent_Include_Path_Error_Message"); //$NON-NLS-1$ |
| 703 |
TraceUtil.outputError(error, include); |
| 704 |
// generateMarker(file, -1, error+include, IMarkerGenerator.SEVERITY_WARNING, fileName); |
| 705 |
} |
| 706 |
} |
| 707 |
// TODO VMIR for now add unresolved paths as well |
| 708 |
translatedIncludes.add(include); |
| 709 |
} |
| 710 |
return translatedIncludes; |
| 711 |
} |
| 712 |
} |