|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.s60tools.util.sourcecode.internal; |
|
19 |
|
20 import java.io.BufferedReader; |
|
21 import java.io.File; |
|
22 import java.io.FileFilter; |
|
23 import java.io.FileInputStream; |
|
24 import java.io.FileNotFoundException; |
|
25 import java.io.FilenameFilter; |
|
26 import java.io.IOException; |
|
27 import java.io.InputStreamReader; |
|
28 import java.util.ArrayList; |
|
29 import java.util.Collection; |
|
30 import java.util.HashSet; |
|
31 import java.util.Iterator; |
|
32 import java.util.Stack; |
|
33 import java.util.regex.Pattern; |
|
34 import com.nokia.s60tools.util.cmdline.CmdLineExeption; |
|
35 import com.nokia.s60tools.util.cmdline.UnsupportedOSException; |
|
36 import com.nokia.s60tools.util.console.IConsolePrintUtility; |
|
37 import com.nokia.s60tools.util.internal.Messages; |
|
38 import com.nokia.s60tools.util.resource.FileUtils; |
|
39 import com.nokia.s60tools.util.sourcecode.CannotFoundFileException; |
|
40 import com.nokia.s60tools.util.sourcecode.ISourceFinder; |
|
41 import com.nokia.s60tools.util.sourcecode.ISourcesFinder; |
|
42 import com.nokia.s60tools.util.sourcecode.SourceFileLocation; |
|
43 |
|
44 /** |
|
45 * Class for founding source file location from .map files. |
|
46 */ |
|
47 public class MapSourceFinder implements ISourceFinder, ISourcesFinder { |
|
48 |
|
49 // |
|
50 // Private constants used in map file seeking and parsing |
|
51 // |
|
52 private static final String CLASS_SEPARATOR = "::";//$NON-NLS-1$ |
|
53 private static final String SEMI_COLON = ";";//$NON-NLS-1$ |
|
54 private static final String COMMENT_START = "/*";//$NON-NLS-1$ |
|
55 private static final String COMMENT_END = "*/";//$NON-NLS-1$ |
|
56 private static final String CODE_COMMENT_PREFIX = "//";//$NON-NLS-1$ |
|
57 private static final String DLL_SUFFIX= ".dll";//$NON-NLS-1$ |
|
58 private static final String BACKSLASH = "\\"; //$NON-NLS-1$ |
|
59 private static final String S60_PATH_PREFIX = BACKSLASH + "s60" + BACKSLASH; //$NON-NLS-1$ |
|
60 private static final String SRC_PATH_PREFIX = BACKSLASH + "src" + BACKSLASH; //$NON-NLS-1$ |
|
61 private static final String S60_PATH_PREFIX_DOUBLE_SLASHS = BACKSLASH + BACKSLASH + "s60" + BACKSLASH + BACKSLASH; //$NON-NLS-1$ |
|
62 private static final String SRC_PATH_PREFIX_DOUBLE_SLASHS = BACKSLASH + BACKSLASH + "src" + BACKSLASH + BACKSLASH; //$NON-NLS-1$ |
|
63 private static final String C_SUFFIX = ".c"; //$NON-NLS-1$ |
|
64 private static final String CPP_SUFFIX = ".cpp"; //$NON-NLS-1$ |
|
65 private static final String METHOD_CLOSING_CHAR = ")"; //$NON-NLS-1$ |
|
66 private static final String METHOD_OPENING_CHAR = "("; //$NON-NLS-1$ |
|
67 private static final String METHOD_DEFINITION_CLOSING_CHAR = "}"; |
|
68 private static final String MAP_FILE_SUFFIX = ".map"; //$NON-NLS-1$ |
|
69 private static final String NULL_ADDRESS = "0x00000000"; //$NON-NLS-1$ |
|
70 private static final String ABSOLUTE = "ABSOLUTE"; //$NON-NLS-1$ |
|
71 private static final String EPOC32_BUILD = "EPOC32\\BUILD"; //$NON-NLS-1$ |
|
72 private static final String EPOC32_BUILD_DOUBLE_SLASHES = "EPOC32\\\\BUILD"; //$NON-NLS-1$ |
|
73 private static final String EXPORT ="EXPORT_C"; //$NON-NLS-1$ |
|
74 private static final String IMPORT = "IMPORT_C"; //$NON-NLS-1$ |
|
75 |
|
76 |
|
77 /** |
|
78 * Print utility used to report error, warnings, and info messages. |
|
79 */ |
|
80 private IConsolePrintUtility printUtility = null; |
|
81 |
|
82 /** |
|
83 * Constructor. |
|
84 * @param printUtility Print utility used to report error, warnings, and info messages. |
|
85 */ |
|
86 public MapSourceFinder(IConsolePrintUtility printUtility){ |
|
87 this.printUtility = printUtility; |
|
88 } |
|
89 |
|
90 /* (non-Javadoc) |
|
91 * @see com.nokia.s60tools.util.sourcecode.ISourceFinder#findSourceFile(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) |
|
92 */ |
|
93 public SourceFileLocation findSourceFile(String ordinal, String methodName, String compoentName, |
|
94 String variant, String build, String epocRootPath) throws CannotFoundFileException { |
|
95 SourceFileLocation sourceLocation = null; |
|
96 try { |
|
97 String address = getAddress(ordinal, compoentName, variant, build, |
|
98 epocRootPath); |
|
99 String mapFilePath = getMapFilePath(compoentName, variant, build, epocRootPath); |
|
100 File mapFile = getMapFile(mapFilePath); |
|
101 |
|
102 String lineWhereAddressIs = getAddressLineFromFile(address, mapFile, methodName); |
|
103 |
|
104 if(methodName == null){ |
|
105 methodName = getMethodNameFromMapFileLine(lineWhereAddressIs); |
|
106 } |
|
107 |
|
108 String objectFileName = getObjectFileName(lineWhereAddressIs, address); |
|
109 sourceLocation = getSourceFileLocation(objectFileName, mapFile, methodName, epocRootPath, isDll(compoentName)); |
|
110 |
|
111 sourceLocation.setDllName(compoentName); |
|
112 sourceLocation.setMethodName(methodName); |
|
113 sourceLocation.setObjectName(objectFileName); |
|
114 sourceLocation.setOrdinal(ordinal); |
|
115 sourceLocation.setMethodAddress(address); |
|
116 |
|
117 } catch (Exception e) { |
|
118 e.printStackTrace(); |
|
119 // Mapping all possible exceptions into single exception type. |
|
120 throw new CannotFoundFileException(e.getMessage(), e); |
|
121 } |
|
122 return sourceLocation; |
|
123 } |
|
124 |
|
125 |
|
126 /* (non-Javadoc) |
|
127 * @see com.nokia.s60tools.util.sourcecode.ISourceFinder#findSourceFile(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.util.Collection) |
|
128 */ |
|
129 public SourceFileLocation findSourceFile(String ordinal, String methodName, String componentName, String epocRootPath, Collection<String> pathsToSeekMapFile) throws CannotFoundFileException { |
|
130 SourceFileLocation sourceLocation = null; |
|
131 try { |
|
132 |
|
133 String mapFileName = componentName + MAP_FILE_SUFFIX; |
|
134 |
|
135 File mapFile = getMapFile(pathsToSeekMapFile, componentName, mapFileName); |
|
136 |
|
137 if(mapFile == null){ |
|
138 String msg = "'" + mapFileName //$NON-NLS-1$ |
|
139 +"' " //$NON-NLS-1$ |
|
140 +Messages.getString("MapSourceFinder.MapFileNotFoundForMethod_ErrMsg_Part1") //$NON-NLS-1$ |
|
141 +methodName |
|
142 +"' " //$NON-NLS-1$ |
|
143 +Messages.getString("MapSourceFinder.MapFileNotFoundForMethod_ErrMsg_Part2"); //$NON-NLS-1$ |
|
144 String consoleMsg = msg + " " //$NON-NLS-1$ |
|
145 +Messages.getString("MapSourceFinder.MapFileNotFoundForMethod_ErrMsg_Part3"); //$NON-NLS-1$ |
|
146 |
|
147 String pathSeparator= ", "; //$NON-NLS-1$ |
|
148 for (Iterator<String> iterator = pathsToSeekMapFile.iterator(); iterator |
|
149 .hasNext();) { |
|
150 String path = (String) iterator.next(); |
|
151 consoleMsg += path + pathSeparator; |
|
152 } |
|
153 consoleMsg = consoleMsg.substring(0, consoleMsg.length() - pathSeparator.length()); |
|
154 printUtility.println(consoleMsg, IConsolePrintUtility.MSG_ERROR); |
|
155 throw new CannotFoundFileException(msg); |
|
156 } |
|
157 File parentDir = mapFile.getParentFile(); |
|
158 |
|
159 String componentPath = parentDir.getAbsolutePath() + File.separatorChar + componentName; |
|
160 |
|
161 String address = getAddress(ordinal, componentPath, epocRootPath); |
|
162 String lineWhereAddressIs = getAddressLineFromFile(address, mapFile, methodName); |
|
163 |
|
164 if(methodName == null){ |
|
165 methodName = getMethodNameFromMapFileLine(lineWhereAddressIs); |
|
166 } |
|
167 |
|
168 String objectFileName = getObjectFileName(lineWhereAddressIs, address); |
|
169 sourceLocation = getSourceFileLocation(objectFileName, mapFile, methodName, epocRootPath, isDll(componentName)); |
|
170 |
|
171 sourceLocation.setDllName(componentName); |
|
172 sourceLocation.setMethodName(methodName); |
|
173 sourceLocation.setObjectName(objectFileName); |
|
174 sourceLocation.setOrdinal(ordinal); |
|
175 sourceLocation.setMethodAddress(address); |
|
176 |
|
177 } catch (Exception e) { |
|
178 e.printStackTrace(); |
|
179 // Mapping all possible exceptions into single exception type. |
|
180 throw new CannotFoundFileException(e.getMessage(), e); |
|
181 } |
|
182 return sourceLocation; |
|
183 } |
|
184 |
|
185 /** |
|
186 * Check if component is DLL or not. |
|
187 * @param componentName Component name. |
|
188 * @return <code>true</code> if component is DLL, otherwise <code>false</code>. |
|
189 */ |
|
190 private boolean isDll(String componentName) { |
|
191 return componentName.trim().endsWith(DLL_SUFFIX) ? true : false; |
|
192 } |
|
193 /** |
|
194 * Gets map file object based on path name if file exists. |
|
195 * @param mapFilePath Path to map file. |
|
196 * @return File object for map file, if file exists, otherwise throwing exception. |
|
197 * @throws FileNotFoundException |
|
198 */ |
|
199 private File getMapFile(String mapFilePath) throws CannotFoundFileException { |
|
200 File mapFile = new File(mapFilePath); |
|
201 if(!mapFile.exists()){ |
|
202 throw new CannotFoundFileException( |
|
203 Messages.getString("MapSourceFinder.MapDoesntExist_ErrMsg_Part1") //$NON-NLS-1$ |
|
204 +mapFilePath |
|
205 +Messages.getString("MapSourceFinder.MapDoesntExist_ErrMsg_Part2")); //$NON-NLS-1$ |
|
206 } |
|
207 return mapFile; |
|
208 } |
|
209 |
|
210 |
|
211 /* (non-Javadoc) |
|
212 * @see com.nokia.s60tools.util.sourcecode.ISourceFinder#findSourceFile(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) |
|
213 */ |
|
214 public SourceFileLocation findSourceFile(String ordinal, String componentName, |
|
215 String variant, String build, String epocRootPath) throws CannotFoundFileException{ |
|
216 |
|
217 return findSourceFile(ordinal, null, componentName, variant, build, epocRootPath); |
|
218 |
|
219 } |
|
220 |
|
221 /** |
|
222 * Tries to find a variant map file for given component. E.g. if component is called MyComponent.exe, |
|
223 * it might not have a map file called MyComponent.exe.map. It might contain a variant map file e.g. |
|
224 * MyComponent.11001011.exe.map. This method tries to find this variant map file MyComponent.11001011.exe.map. |
|
225 * @param epocRootPath EPOCROOT path |
|
226 * @param variant Build variant |
|
227 * @param build Build type (udeb/urel) |
|
228 * @param component Component name. |
|
229 * @return variant map file, or <code>null</code> if not found. |
|
230 */ |
|
231 private File getVariantMapFile(String epocRootPath, String variant, String build, String component) { |
|
232 File variantMapFile = null; |
|
233 |
|
234 String mapPath = |
|
235 epocRootPath + File.separatorChar |
|
236 +SourceFileLocation.EPOC32_FOLDER_NAME + File.separatorChar |
|
237 +SourceFileLocation.RELEASE_FOLDER_NAME + File.separatorChar |
|
238 +variant + File.separatorChar |
|
239 +build + File.separatorChar; |
|
240 mapPath = makeWindowsPath(mapPath); |
|
241 |
|
242 File path = new File(mapPath); |
|
243 if (path.isDirectory() && path.exists()) { |
|
244 |
|
245 final class VariantFilter implements FilenameFilter { |
|
246 String component; |
|
247 public VariantFilter(String componentName) { |
|
248 component = componentName; |
|
249 } |
|
250 public boolean accept(File dir, String name) { |
|
251 if (name.toLowerCase().endsWith(".map")) { |
|
252 int index = component.lastIndexOf("."); |
|
253 if (name.toLowerCase().startsWith(component.substring(0, index+1).toLowerCase())) |
|
254 return true; |
|
255 } |
|
256 return false; |
|
257 } |
|
258 } |
|
259 String[] files = path.list(new VariantFilter(component)); |
|
260 if (files != null && files.length == 1) |
|
261 variantMapFile = new File(mapPath + files[0]); |
|
262 } |
|
263 |
|
264 return variantMapFile; |
|
265 } |
|
266 |
|
267 /* (non-Javadoc) |
|
268 * @see com.nokia.s60tools.util.sourcecode.ISourceFinder#findSourceFileByMethodName(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) |
|
269 */ |
|
270 public SourceFileLocation findSourceFileByMethodName(String methodName, |
|
271 String componentName, String variant, String build, String epocRootPath) throws CannotFoundFileException{ |
|
272 |
|
273 String mapFilePath = getMapFilePath(componentName, variant, build, epocRootPath); |
|
274 |
|
275 File mapFile = null; |
|
276 try { |
|
277 mapFile = getMapFile(mapFilePath); |
|
278 |
|
279 // we could not find map file, try to find variant map file |
|
280 } catch (CannotFoundFileException e) { |
|
281 mapFile = getVariantMapFile(epocRootPath, variant, build, componentName); |
|
282 if (mapFile == null) |
|
283 throw e; |
|
284 } |
|
285 |
|
286 return findSourceFile(methodName, componentName, epocRootPath, mapFile); |
|
287 |
|
288 } |
|
289 |
|
290 /* (non-Javadoc) |
|
291 * @see com.nokia.s60tools.util.sourcecode.ISourceFinder#findSourceFileByMethodName(java.lang.String, java.lang.String, java.lang.String, java.util.Collection) |
|
292 */ |
|
293 public SourceFileLocation findSourceFileByMethodName(String methodName, |
|
294 String componentName, String epocRootPath, Collection<String> pathsToSeekMapFile) throws CannotFoundFileException{ |
|
295 |
|
296 String mapFileName = componentName + MAP_FILE_SUFFIX; |
|
297 File mapFile = getMapFile(pathsToSeekMapFile, componentName, mapFileName); |
|
298 |
|
299 //If we did not found map file, we cannot proceed to src file seek |
|
300 if(mapFile == null){ |
|
301 String msg = "'" + mapFileName //$NON-NLS-1$ |
|
302 +"' " //$NON-NLS-1$ |
|
303 +Messages.getString("MapSourceFinder.MapFileNotFoundForMethod_ErrMsg_Part1") //$NON-NLS-1$ |
|
304 +methodName |
|
305 +"' " //$NON-NLS-1$ |
|
306 +Messages.getString("MapSourceFinder.MapFileNotFoundForMethod_ErrMsg_Part2"); //$NON-NLS-1$ |
|
307 String consoleMsg = msg + " " //$NON-NLS-1$ |
|
308 +Messages.getString("MapSourceFinder.MapFileNotFoundForMethod_ErrMsg_Part3"); //$NON-NLS-1$ |
|
309 |
|
310 String pathSeparator= ", "; //$NON-NLS-1$ |
|
311 for (Iterator<String> iterator = pathsToSeekMapFile.iterator(); iterator |
|
312 .hasNext();) { |
|
313 String path = (String) iterator.next(); |
|
314 consoleMsg += path + pathSeparator; |
|
315 } |
|
316 consoleMsg = consoleMsg.substring(0, consoleMsg.length() - pathSeparator.length()); |
|
317 printUtility.println(consoleMsg, IConsolePrintUtility.MSG_ERROR); |
|
318 throw new CannotFoundFileException(msg); |
|
319 } |
|
320 |
|
321 return findSourceFile(methodName, componentName, epocRootPath, mapFile); |
|
322 |
|
323 } |
|
324 |
|
325 |
|
326 /** |
|
327 * Gets a map file by component name and list of folder where to seek it |
|
328 * @param pathsToSeekMapFile Path list to seek map files from. |
|
329 * @param componentName Component name. |
|
330 * @return file File object pointing to map file and <code>null</code> if not found. |
|
331 */ |
|
332 private File getMapFile(Collection<String> pathsToSeekMapFile, |
|
333 String componentName, String mapFileName) throws CannotFoundFileException { |
|
334 |
|
335 MapFilenameFilter mapFilenameFilter = new MapFilenameFilter(mapFileName); |
|
336 DirFileFilter dirFilter = new DirFileFilter(); |
|
337 |
|
338 for (Iterator<String> iterator = pathsToSeekMapFile.iterator(); iterator |
|
339 .hasNext();) { |
|
340 String path = (String) iterator.next(); |
|
341 File dir = new File(path); |
|
342 if(!dir.exists() || !dir.isDirectory()){ |
|
343 continue; |
|
344 } |
|
345 File mapFile = getFileFromDir(dir, mapFileName, mapFilenameFilter, dirFilter); |
|
346 if(mapFile != null){ |
|
347 return mapFile; |
|
348 } |
|
349 |
|
350 } |
|
351 |
|
352 return null; |
|
353 } |
|
354 |
|
355 /** |
|
356 * Get map file from dir and dirs under given dir. Calls recursively it self. |
|
357 * @param dir Directory to search for. |
|
358 * @param mapFileName Map file name to search for. |
|
359 * @param mapFilenameFilter Map file name filter. |
|
360 * @param dirFilter Directory filter. |
|
361 * @return mapFile with given name, or null if cannot be found |
|
362 */ |
|
363 private File getFileFromDir(File dir, String mapFileName, MapFilenameFilter mapFilenameFilter, DirFileFilter dirFilter){ |
|
364 |
|
365 File [] files = dir.listFiles(mapFilenameFilter); |
|
366 if(files != null && files.length > 0){ |
|
367 return files[0]; |
|
368 } |
|
369 |
|
370 File [] dirs = dir.listFiles(dirFilter); |
|
371 for (int i = 0; i < dirs.length; i++) { |
|
372 File mapFile = getFileFromDir(dirs[i], mapFileName, mapFilenameFilter, dirFilter); |
|
373 if(mapFile != null){ |
|
374 return mapFile; |
|
375 } |
|
376 } |
|
377 return null; |
|
378 |
|
379 } |
|
380 |
|
381 /** |
|
382 * Filter accepts only directories, not files |
|
383 */ |
|
384 private class DirFileFilter implements FileFilter { |
|
385 |
|
386 public boolean accept(File file) { |
|
387 return file.isDirectory(); |
|
388 } |
|
389 } |
|
390 |
|
391 /** |
|
392 * Filter accepts only files named by given file (case in sensitive) |
|
393 */ |
|
394 private class MapFilenameFilter implements FilenameFilter{ |
|
395 |
|
396 private String mapFileName = null; |
|
397 |
|
398 private MapFilenameFilter(){ |
|
399 } |
|
400 public MapFilenameFilter(String mapFileName){ |
|
401 this(); |
|
402 this.mapFileName = mapFileName; |
|
403 } |
|
404 |
|
405 public boolean accept(File dir, String name) { |
|
406 return name.equalsIgnoreCase(mapFileName) ? true : false; |
|
407 } |
|
408 } |
|
409 |
|
410 /** |
|
411 * Finds source file based on the method name. |
|
412 * @param methodName Method name. |
|
413 * @param componentName Component name. |
|
414 * @param epocRootPath EPOCROOT path. |
|
415 * @param mapFile File object pointing to MMP file. |
|
416 * @return source file location, or <code>null</code> if not found. |
|
417 * @throws CannotFoundFileException |
|
418 */ |
|
419 private SourceFileLocation findSourceFile(String methodName, |
|
420 String componentName, String epocRootPath, File mapFile) |
|
421 throws CannotFoundFileException { |
|
422 try { |
|
423 // Example method name line |
|
424 //20 CRepository::Create(unsigned long, TDesC16 const&) |
|
425 |
|
426 String lineWhereAddressIs = getAddressLineFromFile(mapFile, methodName); |
|
427 String address = getAddresFromLine(lineWhereAddressIs, methodName); |
|
428 |
|
429 String objectFileName = getObjectFileName(lineWhereAddressIs, address); |
|
430 String shortMethodNameWithoutParams = getMethodNameWithoutParams(methodName); |
|
431 SourceFileLocation sourceLocation = getSourceFileLocation(objectFileName, mapFile, shortMethodNameWithoutParams, epocRootPath, isDll(componentName)); |
|
432 |
|
433 sourceLocation.setDllName(componentName); |
|
434 sourceLocation.setMethodAddress(address); |
|
435 sourceLocation.setMethodName(methodName); |
|
436 sourceLocation.setObjectName(objectFileName); |
|
437 sourceLocation.setMethodAddress(address); |
|
438 return sourceLocation; |
|
439 |
|
440 } catch (Exception e) { |
|
441 e.printStackTrace(); |
|
442 // Mapping all possible exceptions into single exception type. |
|
443 throw new CannotFoundFileException(e.getMessage() , e); |
|
444 } |
|
445 } |
|
446 |
|
447 /** |
|
448 * Get address from map file line based on method name |
|
449 * @param lineWhereAddressIs Line containing address. |
|
450 * @param methodName Method name. |
|
451 * @return Method address. |
|
452 */ |
|
453 private String getAddresFromLine(String lineWhereAddressIs, |
|
454 String methodName) { |
|
455 //e.g. : CRepository::Create(unsigned long, const TDesC16&) 0x000080b9 Thumb Code 8 centralrepository.in(.text) |
|
456 String addString = lineWhereAddressIs.substring(lineWhereAddressIs.indexOf(methodName) + methodName.length()).trim(); |
|
457 //e.g. : '0x000080b9 Thumb Code 8 centralrepository.in(.text)' |
|
458 addString = addString.substring(0, addString.indexOf(" ")).trim(); //$NON-NLS-1$ |
|
459 return addString; |
|
460 } |
|
461 |
|
462 |
|
463 /** |
|
464 * Get Address using petran command-line runner. |
|
465 * @param ordinal Method ordinal. |
|
466 * @param componentName Component name. |
|
467 * @param variant Build variant. |
|
468 * @param build Build type (urel/udeb). |
|
469 * @param epocRootPath EPOCROOT path. |
|
470 * @return Address for the given method ordinal. |
|
471 * @throws UnsupportedOSException |
|
472 * @throws InterruptedException |
|
473 * @throws CmdLineExeption |
|
474 */ |
|
475 private String getAddress(String ordinal, String componentName, String variant, |
|
476 String build, String epocRootPath) throws UnsupportedOSException, |
|
477 InterruptedException, CmdLineExeption { |
|
478 |
|
479 PetranDumpCMDLineRunner runner = new PetranDumpCMDLineRunner(printUtility); |
|
480 String address = runner.getAddress(ordinal, componentName, variant, build, epocRootPath); |
|
481 return address; |
|
482 } |
|
483 |
|
484 /** |
|
485 * Get Address using petran command-line runner. |
|
486 * @param ordinal Method ordinal |
|
487 * @param componentPath path of the component |
|
488 * @param epocRootPath EPOCROOT path |
|
489 * @return Address for the given method ordinal. |
|
490 * @throws UnsupportedOSException |
|
491 * @throws InterruptedException |
|
492 * @throws CmdLineExeption |
|
493 */ |
|
494 private String getAddress(String ordinal, String componentPath, String epocRootPath) throws UnsupportedOSException, |
|
495 InterruptedException, CmdLineExeption { |
|
496 |
|
497 PetranDumpCMDLineRunner runner = new PetranDumpCMDLineRunner(printUtility); |
|
498 String address = runner.getAddress(ordinal, componentPath, epocRootPath); |
|
499 return address; |
|
500 } |
|
501 |
|
502 /** |
|
503 * Get sourceFile location |
|
504 * @param objectFileName Object file name. |
|
505 * @param mapFile File object pointing to map file. |
|
506 * @param methodName Method name. |
|
507 * @param epocRootPath EPOCROOT path. |
|
508 * @param isDll <code>true</code> if component is DLL, otherwise <code>false</code>. |
|
509 * @return path in Windows format, separators will be "\":s even when they were "/":s originally. |
|
510 * @throws IOException |
|
511 * @throws CannotFoundFileException |
|
512 */ |
|
513 private SourceFileLocation getSourceFileLocation(String objectFileName, File mapFile, String methodName, String epocRootPath, boolean isDll) throws IOException, CannotFoundFileException { |
|
514 FileInputStream in = null; |
|
515 InputStreamReader isr = null; |
|
516 BufferedReader br = null; |
|
517 ArrayList<String> lines = new ArrayList<String>(); |
|
518 SourceFileLocation sourceLocation = null; |
|
519 |
|
520 try { |
|
521 in = new FileInputStream(mapFile); |
|
522 isr = new InputStreamReader(in); |
|
523 br = new BufferedReader(isr); |
|
524 |
|
525 String line = null; |
|
526 //seek "0x00000000" and "ABSOLUTE" and object file name from file line by line |
|
527 while ((line = br.readLine()) != null) { |
|
528 if(line.contains(objectFileName) && |
|
529 line.contains(NULL_ADDRESS) && |
|
530 line.contains(ABSOLUTE) ){ |
|
531 |
|
532 //if we found wanted text, checking that it does not contain |
|
533 //\EPOC32\BUILD or \\EPOC32\\BUILD, because then its not a source, but build file |
|
534 //Returning path in windows format |
|
535 String epocBuildLine = makeWindowsPath(line); |
|
536 //Making sure that souce location does not point to BUILD folder |
|
537 if(epocBuildLine.indexOf(EPOC32_BUILD) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
538 epocBuildLine = epocBuildLine.substring(0, epocBuildLine.indexOf(NULL_ADDRESS)).trim(); |
|
539 lines.add(epocBuildLine); |
|
540 } |
|
541 |
|
542 } |
|
543 } |
|
544 |
|
545 //If there was only one line |
|
546 if(lines.size() == 1){ |
|
547 String filePath = buildAbsoluteFilePath(lines.get(0), epocRootPath); |
|
548 if(sourceFileExist(filePath)){ |
|
549 sourceLocation = new SourceFileLocation(); |
|
550 sourceLocation.setSourceFileLocation(filePath); |
|
551 String methodNameWithoutParams = getMethodNameWithoutParams(methodName); |
|
552 int offset = getMethodNameLineOfsetFromSourceFile(methodNameWithoutParams, new File(filePath), isDll); |
|
553 if(offset != SourceFileLocation.OFFSET_NOT_FOUND){ |
|
554 sourceLocation.setMethodOffset(offset); |
|
555 } |
|
556 }else{ |
|
557 String msg = Messages.getString("MapSourceFinder.ObjectFileDoesntExist_ErrMsg_Part1") +objectFileName //$NON-NLS-1$ //$NON-NLS-2$ |
|
558 +Messages.getString("MapSourceFinder.ObjectFileDoesntExist_ErrMsg_Part2") + mapFile.getAbsolutePath() //$NON-NLS-1$ //$NON-NLS-2$ |
|
559 +Messages.getString("MapSourceFinder.ObjectFileDoesntExist_ErrMsg_Part3") + filePath//$NON-NLS-1$ //$NON-NLS-2$ |
|
560 +Messages.getString("MapSourceFinder.ObjectFileDoesntExist_ErrMsg_Part4");//$NON-NLS-1$ |
|
561 printUtility.println(msg); |
|
562 throwCannotFoundFileException(mapFile, methodName, msg); |
|
563 } |
|
564 } |
|
565 //If there was many occurrences, opening files and seek method name, to get only one result |
|
566 else if(lines.size() > 0){ |
|
567 sourceLocation = foundSourceFileWhereMethodIsImplemented(lines, methodName, epocRootPath, isDll); |
|
568 |
|
569 if(sourceLocation == null){ |
|
570 String msg = Messages.getString("MapSourceFinder.SourceFileNotFoundForMethod_ErrMsg_Part1") //$NON-NLS-1$ |
|
571 +methodName + Messages.getString("MapSourceFinder.SourceFileNotFoundForMethod_ErrMsg_Part2") +mapFile.getAbsolutePath() +"'."; //$NON-NLS-1$ //$NON-NLS-2$ |
|
572 printUtility.println(msg); |
|
573 |
|
574 throwCannotFoundFileException(mapFile, methodName, msg); |
|
575 } |
|
576 |
|
577 }//No results found |
|
578 else{ |
|
579 String msg = Messages.getString("MapSourceFinder.ObjectFileNotFound_ErrMsg_Part1") +objectFileName +Messages.getString("MapSourceFinder.ObjectFileNotFound_ErrMsg_Part2") + mapFile.getAbsolutePath() +"'."; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
580 printUtility.println(msg); |
|
581 throwCannotFoundFileException(mapFile, methodName, msg); |
|
582 |
|
583 } |
|
584 |
|
585 } finally{ |
|
586 if(in != null){ |
|
587 in.close(); |
|
588 } |
|
589 if(isr != null){ |
|
590 isr.close(); |
|
591 } |
|
592 if(br != null){ |
|
593 br.close(); |
|
594 } |
|
595 } |
|
596 |
|
597 return sourceLocation; |
|
598 } |
|
599 |
|
600 /** |
|
601 * Throw an exception with message about map file and method name, that a source file cannot be found from those details |
|
602 * @param mapFile File object pointing to map file. |
|
603 * @param methodName Method name. |
|
604 * @throws CannotFoundFileException |
|
605 */ |
|
606 private void throwCannotFoundFileException(File mapFile, String methodName, String msg) throws CannotFoundFileException{ |
|
607 throw new CannotFoundFileException(msg); |
|
608 } |
|
609 |
|
610 |
|
611 /** |
|
612 * Converts path into Windows format by |
|
613 * replacing extra "\\":s and replace "/" with "\". |
|
614 * @param path Path name string to convert. |
|
615 * @return path name string in windows format |
|
616 */ |
|
617 private String makeWindowsPath(String path) { |
|
618 //fixing slashes so we can find epoc32 build folder in any cases. |
|
619 //First replacing "\"'s with "/"'s so regular expression will work |
|
620 String windowsPath = path.replace(BACKSLASH, "/" ); //$NON-NLS-1$ //$NON-NLS-2$ |
|
621 //removing multiple backslashes: " +" means more than one white spaces, e.g. "a b c" -> "a b c" |
|
622 windowsPath = windowsPath.replaceAll("/+", "/"); //$NON-NLS-1$ //$NON-NLS-2$ |
|
623 windowsPath = windowsPath.replace("/", BACKSLASH); //$NON-NLS-1$ //$NON-NLS-2$ |
|
624 return windowsPath; |
|
625 } |
|
626 |
|
627 /** |
|
628 * Checks if file exists. |
|
629 * @param filePath File path name. |
|
630 * @return <code>true</code> if exist, otherwise <code>false</code>. |
|
631 */ |
|
632 private boolean sourceFileExist(String filePath) { |
|
633 File file = new File(filePath); |
|
634 return file.exists(); |
|
635 } |
|
636 /** |
|
637 * Builds absolute file path name from source file path and EPOCROOT path |
|
638 * @param srcPath File source path |
|
639 * @param epocRootPath EPOCROOT path |
|
640 * @return Absolute file path name. |
|
641 */ |
|
642 private String buildAbsoluteFilePath(String srcPath, String epocRootPath) { |
|
643 String filePath; |
|
644 |
|
645 srcPath = FileUtils.removeDriveLetterPortionFromPathIfExists(srcPath); |
|
646 |
|
647 if(epocRootPath.endsWith(File.separator) && srcPath.startsWith(File.separator)){ |
|
648 filePath = epocRootPath + srcPath; |
|
649 } |
|
650 else if(epocRootPath.endsWith(File.separator) || srcPath.startsWith(File.separator) ){ |
|
651 filePath = epocRootPath + srcPath; |
|
652 } |
|
653 else{ |
|
654 filePath = epocRootPath + File.separatorChar + srcPath; |
|
655 } |
|
656 |
|
657 //Removing possible double slashes |
|
658 filePath = makeWindowsPath(filePath); |
|
659 |
|
660 return filePath; |
|
661 } |
|
662 |
|
663 /** |
|
664 * Check if source files contains method name, if contains, returning that file location. |
|
665 * Skips parameters, only seeking method name or ClassName::MethodName if given. |
|
666 * @param lines containing paths to source files found in .map file |
|
667 * @param methodName Method name. |
|
668 * @param epocRootPath EPOCROOT path. |
|
669 * @param isDll <code>true</code> if component is DLL, otherwise <code>false</code>. |
|
670 * @return Source file path if method name without parameters is found from that file, or <code>null</code> if not found |
|
671 * @throws IOException |
|
672 * @throws FileNotFoundException |
|
673 * @throws CannotFoundFileException |
|
674 */ |
|
675 private SourceFileLocation foundSourceFileWhereMethodIsImplemented(ArrayList<String> lines, |
|
676 String methodName, String epocRootPath, boolean isDll) throws FileNotFoundException, IOException, CannotFoundFileException { |
|
677 |
|
678 File srcFile; |
|
679 //Seeking lines where is source file paths one by one |
|
680 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) { |
|
681 String path = (String) iterator.next(); |
|
682 srcFile = buildSourceFileObject(path, epocRootPath, methodName); |
|
683 |
|
684 if(srcFile.exists()){ |
|
685 String methodNameWithOutParams = getMethodNameWithoutParams(methodName); |
|
686 |
|
687 int methodLineOfset = getMethodNameLineOfsetFromSourceFile(methodNameWithOutParams, srcFile, isDll); |
|
688 //If we found a file where is classname::methodname, stop searching and return that one. |
|
689 if(methodLineOfset != SourceFileLocation.OFFSET_NOT_FOUND){ |
|
690 SourceFileLocation sourceLocation = new SourceFileLocation(); |
|
691 sourceLocation.setSourceFileLocation(srcFile.getAbsolutePath()); |
|
692 sourceLocation.setMethodOffset(methodLineOfset); |
|
693 return sourceLocation; |
|
694 } |
|
695 }else{ |
|
696 //Caller will throw an exception if null returned |
|
697 printUtility.println(Messages.getString("MapSourceFinder.FileDoesntExist_ErrMsg_Part1") +srcFile.getAbsolutePath() //$NON-NLS-1$ |
|
698 + Messages.getString("MapSourceFinder.FileDoesntExist_ErrMsg_Part2") +methodName +Messages.getString("MapSourceFinder.FileDoesntExist_ErrMsg_Part3")); //$NON-NLS-1$ //$NON-NLS-2$ |
|
699 } |
|
700 } |
|
701 return null; |
|
702 } |
|
703 |
|
704 /** |
|
705 * Builds alternate source path from the parameters in case the default behavior has failed. |
|
706 * @param path Source file path found from *.map-file. |
|
707 * @param epocRootPath EPOCROOT defined in SDK properties. |
|
708 * @param methodName Name of the method we were about to search. |
|
709 * @return Alternate file path, if found. |
|
710 */ |
|
711 private File buildSourceFileObject(String path, String epocRootPath, String methodName) { |
|
712 |
|
713 // Default behavior is to add 'source path' to EPOCROOT. (format used in platform built map-files) |
|
714 String srcFileUri = buildAbsoluteFilePath(path, epocRootPath); |
|
715 File srcFile = new File(srcFileUri); |
|
716 |
|
717 // Checking if the default behavior resulted correct file name |
|
718 if(!srcFile.exists()){ |
|
719 // Printing info to console about the operation |
|
720 printUtility.println(Messages.getString("MapSourceFinder.FileDoesntExist_ErrMsg_Part1") +srcFile.getAbsolutePath() //$NON-NLS-1$ |
|
721 + Messages.getString("MapSourceFinder.FileDoesntExist_ErrMsg_Part2") +methodName +Messages.getString("MapSourceFinder.FileDoesntExist_ErrMsg_Part3")); //$NON-NLS-1$ //$NON-NLS-2$ |
|
722 // Checking if the source path already contained EPOCROOT, and stripping it. |
|
723 srcFile = stripEpocRootFromPath(path, epocRootPath, srcFile); |
|
724 } |
|
725 |
|
726 return srcFile; |
|
727 } |
|
728 /** |
|
729 * Checks if given path already contains EPOCROOT without logical drive letter. |
|
730 * If contains, then stripping it away and returning file object containing correct path. |
|
731 * @param path Original source path in map-file |
|
732 * @param epocRootPath Currently used EPOCROOT |
|
733 * @param srcFile Currently used source file absolute path (possibly containing already EPOCROOT). |
|
734 * @return File object containing correct path without duplicate EPOCROOT, or current file object |
|
735 * as result if there was no overlapping. |
|
736 */ |
|
737 private File stripEpocRootFromPath(String path, String epocRootPath, File srcFile) { |
|
738 // For components that user has build in Carbide has different kind of source path used. |
|
739 // The source path in map-file may already include EPOCROOT e.g. in the following example: |
|
740 // |
|
741 // EPOCROOT=C:\foo\bar\MySDK\ |
|
742 // Source file path found from *.map-file=\foo\bar\MySDK\MyExamples\MyExample\ENGINE\src\enginedll.cpp |
|
743 // |
|
744 String epocRootWithoutDrive = epocRootPath.substring(2); // Skipping drive letter and colon: "C:" |
|
745 |
|
746 if(path.startsWith(epocRootWithoutDrive)){ |
|
747 // Stripping EPOCROOT |
|
748 String altSrcFileUri = path.substring(epocRootWithoutDrive.length()); |
|
749 srcFile = new File(epocRootPath + altSrcFileUri); |
|
750 // Printing info to console about the operation |
|
751 printUtility.println(Messages.getString("MapSourceFinder.StrippingEpocrootFromPath_InfoMsg")); //$NON-NLS-1$ |
|
752 } |
|
753 return srcFile; |
|
754 } |
|
755 |
|
756 /** |
|
757 * Parses out params from method name |
|
758 * @param methodName Name of the method to parse. |
|
759 * @return Method name without parameters. |
|
760 */ |
|
761 private String getMethodNameWithoutParams(String methodName) { |
|
762 |
|
763 //ContentAccess::CData::NewL(RFile&, TDesC16 const&, ContentAccess::TIntent) |
|
764 String methodNameWithClassButWithOutParams = methodName.split(Pattern.quote(METHOD_OPENING_CHAR))[0]; |
|
765 String methodNameWithOutParams; |
|
766 |
|
767 String classSeparator = CLASS_SEPARATOR; |
|
768 if(methodNameWithClassButWithOutParams.indexOf(classSeparator) != -1){ |
|
769 String [] parts = methodNameWithClassButWithOutParams.split(Pattern.quote(classSeparator)); |
|
770 methodNameWithOutParams = parts[parts.length - 2] +classSeparator + parts[parts.length -1]; |
|
771 }else{ |
|
772 methodNameWithOutParams = methodNameWithClassButWithOutParams; |
|
773 } |
|
774 |
|
775 //If that file contains line, where is methodname, e.g. MyClass:MyMethod then that file is what we want |
|
776 //Only Class name and method name is searched, skipping parameters because of possible new lines and so on. |
|
777 return methodNameWithOutParams; |
|
778 } |
|
779 |
|
780 /** |
|
781 * Get object filename from line where method address was found |
|
782 * @param lineWhereAddressIs Line containing the address and object file name. |
|
783 * @param address Method address |
|
784 * @return object file name |
|
785 */ |
|
786 private String getObjectFileName(String lineWhereAddressIs, String address) { |
|
787 |
|
788 //First line should be e.g.: |
|
789 //CRepository::Create(unsigned long, const TDesC16&) 0x000080b9 Thumb Code 8 centralrepository.in(.text) |
|
790 //or/ |
|
791 //User::LeaveIfError(int) 0x00009078 ARM Code 0 euser{000a0000}-593.o(StubCode) |
|
792 |
|
793 //Cut string after address |
|
794 String objFileName = lineWhereAddressIs.substring(lineWhereAddressIs.indexOf(address) +address.length()).trim(); |
|
795 //No there should be: "Thumb Code 8 centralrepository.in(.text)" |
|
796 //or: "ARM Code 0 euser{000a0000}-593.o(StubCode)" |
|
797 |
|
798 //Cut string before "(" |
|
799 objFileName = objFileName.substring(0, objFileName.lastIndexOf(METHOD_OPENING_CHAR)).trim(); |
|
800 //No there should be: "Thumb Code 8 centralrepository.in" |
|
801 //or: "ARM Code 0 euser{000a0000}-593.o" |
|
802 |
|
803 //Cut string from last " " |
|
804 objFileName = objFileName.substring(objFileName.lastIndexOf(" ")).trim(); //$NON-NLS-1$ |
|
805 |
|
806 //No there should be: "centralrepository.in" |
|
807 //or: "euser{000a0000}-593.o" |
|
808 |
|
809 return objFileName; |
|
810 } |
|
811 |
|
812 /** |
|
813 * Get method name from line where method address was found. |
|
814 * @param lineWhereAddressIs Line containing the address and object file name. |
|
815 * @return method name |
|
816 */ |
|
817 private String getMethodNameFromMapFileLine(String lineWhereAddressIs) { |
|
818 //CRepository::Create(unsigned long, const TDesC16&) 0x000080b9 Thumb Code 8 centralrepository.in(.text) |
|
819 String method = lineWhereAddressIs.substring(0, lineWhereAddressIs.indexOf(METHOD_CLOSING_CHAR)); |
|
820 return method != null ? method.trim() : null; |
|
821 } |
|
822 |
|
823 /** |
|
824 * Get those lines from file, where is the wanted string. |
|
825 * @param wantedString wanted string, or <code>null</code> if all lines is wanted |
|
826 * @param file File object to search for the string. |
|
827 * @param addAllLinesIfWantedStringExist If set to <code>true</code> and wantedString |
|
828 * occurs at least once, all lines from file will be returned, |
|
829 * otherwise an empty list will be returned, |
|
830 * If set to <code>false</code>, only those lines where |
|
831 * wanted string exist will be returned. |
|
832 * @return Lines based wanted strings and boolean parameter setting. |
|
833 * @throws IOException |
|
834 */ |
|
835 private ArrayList<String> getLinesFromFile(String wantedString, File file, boolean addAllLinesIfWantedStringExist) throws IOException{ |
|
836 ArrayList<String> lines = new ArrayList<String>(); |
|
837 FileInputStream in = null; |
|
838 InputStreamReader isr = null; |
|
839 BufferedReader br = null; |
|
840 boolean fileContainsWantedString = false; |
|
841 |
|
842 try { |
|
843 in = new FileInputStream(file); |
|
844 isr = new InputStreamReader(in); |
|
845 br = new BufferedReader(isr); |
|
846 |
|
847 String line = null; |
|
848 |
|
849 //seek wanted text from file line by line |
|
850 while ((line = br.readLine()) != null) { |
|
851 //if we found wanted text, stopping search |
|
852 if(addAllLinesIfWantedStringExist){ |
|
853 lines.add(line); |
|
854 //Marking that we found a required line from that file when all lines is gathered |
|
855 if(line.contains(wantedString)){ |
|
856 fileContainsWantedString = true; |
|
857 } |
|
858 } |
|
859 else if(!addAllLinesIfWantedStringExist && line.contains(wantedString)){ |
|
860 lines.add(line); |
|
861 }//Else line is not wanted and will not be added to lines |
|
862 } |
|
863 }finally{ |
|
864 if(in != null){ |
|
865 in.close(); |
|
866 } |
|
867 if(isr != null){ |
|
868 isr.close(); |
|
869 } |
|
870 if(br != null){ |
|
871 br.close(); |
|
872 } |
|
873 } |
|
874 |
|
875 //If we want all lines from file and that file does not contain wanted String |
|
876 //we collect already all lines but there was no wanted line, so returning new empty list |
|
877 if(addAllLinesIfWantedStringExist && !fileContainsWantedString){ |
|
878 return new ArrayList<String>(); |
|
879 }else{ |
|
880 return lines; |
|
881 } |
|
882 } |
|
883 |
|
884 |
|
885 /** |
|
886 * Seek address line where is method address and braces (). |
|
887 * @param address Method address. |
|
888 * @param mapFile File object pointing to map file. |
|
889 * @param methodName Method name. |
|
890 * @return Address line. |
|
891 * @throws FileNotFoundException |
|
892 * @throws IOException |
|
893 * @throws CannotFoundFileException |
|
894 */ |
|
895 private String getAddressLineFromFile(String address, File mapFile, String methodName) |
|
896 throws FileNotFoundException, IOException, CannotFoundFileException { |
|
897 |
|
898 ArrayList<String> lines = getLinesFromFile(address, mapFile, false); |
|
899 String wantedLine = null; |
|
900 |
|
901 //If there was only one occurrence |
|
902 if(lines.size() == 1){ |
|
903 wantedLine = lines.get(0); |
|
904 |
|
905 } |
|
906 //If there was many occurences, selecting wanted one |
|
907 else if(lines.size() > 1){ |
|
908 |
|
909 //Seeking all foundings and select wanted line |
|
910 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) { |
|
911 String aLine = (String) iterator.next(); |
|
912 |
|
913 //If there is many lines, we want that one where method name is, |
|
914 //and in method name lines, there will be braces "()" before address e.g. in XnResource.dll.map |
|
915 //StubCode 0x000084b8 Section 8 apmime{000a0000}-57.o(StubCode) |
|
916 //TDataType::InternalizeL(RReadStream&) 0x000084b8 ARM Code 0 apmime{000a0000}-57.o(StubCode) |
|
917 |
|
918 //cut string before address |
|
919 aLine = aLine.substring(aLine.indexOf(address)); |
|
920 if(aLine.contains(METHOD_CLOSING_CHAR) && aLine.contains(METHOD_OPENING_CHAR)){ |
|
921 |
|
922 wantedLine = aLine; |
|
923 break; |
|
924 } |
|
925 |
|
926 } |
|
927 |
|
928 }//else wantedLine will be null and exception will thrown |
|
929 |
|
930 if(wantedLine == null){ |
|
931 throw new CannotFoundFileException( |
|
932 Messages.getString("MapSourceFinder.CannotFoundAddress_ErrMsg_Part1") +methodName +Messages.getString("MapSourceFinder.CannotFoundAddress_ErrMsg_Part2") +mapFile.getName() +"'."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
933 } |
|
934 |
|
935 return wantedLine; |
|
936 } |
|
937 |
|
938 |
|
939 /** |
|
940 * Seek address line where is method name and braces (). |
|
941 * @param mapFile File object pointing to map file. |
|
942 * @param methodName Method name. |
|
943 * @return Address line. |
|
944 * @throws FileNotFoundException |
|
945 * @throws IOException |
|
946 * @throws CannotFoundFileException |
|
947 */ |
|
948 private String getAddressLineFromFile(File mapFile, String methodName) |
|
949 throws FileNotFoundException, IOException, CannotFoundFileException { |
|
950 |
|
951 //Line is e.g: |
|
952 //CTerminalControlSession::GetDeviceLockParameterL(TBuf8<(int)21>&, int) 0x000090e1 Thumb Code 188 TerminalControl.in(.text) |
|
953 //When method is: CTerminalControlSession::GetDeviceLockParameterL(TBuf8<(int)21>&, int) |
|
954 |
|
955 ArrayList<String> lines = getLinesFromFile(methodName, mapFile, false); |
|
956 String wantedLine = null; |
|
957 |
|
958 //If there was only one occurrence |
|
959 if(lines.size() == 1){ |
|
960 wantedLine = lines.get(0); |
|
961 |
|
962 } |
|
963 //If there was many occurrences, selecting wanted one |
|
964 else if(lines.size() > 1){ |
|
965 |
|
966 //Seeking all findings and select wanted line |
|
967 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) { |
|
968 String aLine = (String) iterator.next(); |
|
969 //What to do if many lines found? Currently just printing a debug message. |
|
970 //Really it should not be happening, but if does, logic must be improved if error situation occurs. |
|
971 printUtility.println( |
|
972 Messages.getString("MapSourceFinder.ManyAddressLines_Msg_Part_1") //$NON-NLS-1$ |
|
973 +methodName |
|
974 +Messages.getString("MapSourceFinder.ManyAddressLines_Msg_Part_2") //$NON-NLS-1$ |
|
975 +mapFile.getName() |
|
976 +Messages.getString("MapSourceFinder.ManyAddressLines_Msg_Part_3")//$NON-NLS-1$ |
|
977 +aLine |
|
978 +"'."); //$NON-NLS-1$ |
|
979 |
|
980 } |
|
981 //Even if there is many lines, just selecting the first one |
|
982 wantedLine = lines.get(0); |
|
983 |
|
984 }//else wantedLine will be null and exception will thrown |
|
985 |
|
986 if(wantedLine == null){ |
|
987 throw new CannotFoundFileException( |
|
988 Messages.getString("MapSourceFinder.CannotFoundAddress_ErrMsg_Part1") +methodName +Messages.getString("MapSourceFinder.CannotFoundAddress_ErrMsg_Part2") +mapFile.getName() +"'."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
989 } |
|
990 |
|
991 return wantedLine; |
|
992 } |
|
993 |
|
994 |
|
995 /** |
|
996 * Seek offset from method implementation from source file. |
|
997 * @param methodName Method name |
|
998 * @param file File to gen method name line offset. |
|
999 * @param isDll When set to <code>true</code> tells that implementation must |
|
1000 * have prefix IMPORT_C or EXPORT_C and if set to <code>false</code> |
|
1001 * we suppose that it is exe file in question and those are not required. |
|
1002 * @return Offset or -1 if not found |
|
1003 * @throws FileNotFoundException |
|
1004 * @throws IOException |
|
1005 */ |
|
1006 private int getMethodNameLineOfsetFromSourceFile(String methodName, File file, boolean isDll) |
|
1007 throws FileNotFoundException, IOException { |
|
1008 //getting all lines of that file if it contains methodName at least some where |
|
1009 ArrayList<String> lines = getLinesFromFile(methodName, file, true); |
|
1010 String wantedLine = null; |
|
1011 int offset = SourceFileLocation.OFFSET_NOT_FOUND;//-1 will return if offset cannot be found from file |
|
1012 // If there was at least one occurrence of methodName |
|
1013 if (lines.size() > 0) { |
|
1014 |
|
1015 //For finding offset of method implementation, we need to collect file contents |
|
1016 StringBuffer fileBuffer = new StringBuffer(); |
|
1017 StringBuffer tmpBuffer = null; |
|
1018 boolean isInsideCommentSegment = false; |
|
1019 boolean searchForMethodDefinition = false; |
|
1020 String methodStartingLine = null; |
|
1021 |
|
1022 // Seeking all findings and select wanted line |
|
1023 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) { |
|
1024 String aLine = (String) iterator.next();//Not to be modified |
|
1025 fileBuffer.append(aLine);//for founding out offset collecting file to buffer |
|
1026 fileBuffer.append("\r\n"); //$NON-NLS-1$ |
|
1027 String lineWithoutComments = aLine; |
|
1028 |
|
1029 //If we are inside of comment segment, and this line does not contain comment segment closing |
|
1030 //we can just skip the line because its a comment line. |
|
1031 if(isInsideCommentSegment && lineWithoutComments.indexOf(COMMENT_END) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1032 continue; |
|
1033 } |
|
1034 //if we are inside of comment segment and this line contains comment closing segment |
|
1035 //checking out if there is something after that comment segment line |
|
1036 else if(isInsideCommentSegment && lineWithoutComments.indexOf(COMMENT_END) != SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1037 |
|
1038 lineWithoutComments = getLineWithOutComments(lineWithoutComments, isInsideCommentSegment); |
|
1039 |
|
1040 //mark that comment segment is closed if so |
|
1041 isInsideCommentSegment = isLineClosingCommentSegment(lineWithoutComments); |
|
1042 } |
|
1043 |
|
1044 //if that line contains opening sequence to comment segment |
|
1045 else if(lineWithoutComments.indexOf(COMMENT_START) != SourceFileLocation.OFFSET_NOT_FOUND ){ |
|
1046 |
|
1047 //case 1 / ** <comments> |
|
1048 //case 2 ..Text / ** <comments> * / Text.. |
|
1049 //case 3 / ** <comments> * / Text.. |
|
1050 |
|
1051 isInsideCommentSegment = isLineOpeningCommentSegment(lineWithoutComments); |
|
1052 lineWithoutComments = getLineWithOutComments(lineWithoutComments, isInsideCommentSegment); |
|
1053 } |
|
1054 //Else in this line there is no comment segment, and status nor line needs no modifications |
|
1055 |
|
1056 //if this line does not contain methodName, just continue |
|
1057 if(!searchForMethodDefinition && (isInsideCommentSegment || !lineWithoutComments.contains(methodName)) /*|| isCommentLine*/){ |
|
1058 continue; |
|
1059 } |
|
1060 boolean isCommentLine = isCommentLine(lineWithoutComments, methodName); |
|
1061 //if this line does not contain methodName, just continue |
|
1062 if(!searchForMethodDefinition && (isInsideCommentSegment || !lineWithoutComments.contains(methodName) || isCommentLine)){ |
|
1063 continue; |
|
1064 } |
|
1065 |
|
1066 //Cut the line, because there can be e.g. MyClass::MyMethod() //;;; When ";" would cause line to drop out |
|
1067 if(lineWithoutComments.indexOf(CODE_COMMENT_PREFIX) != SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1068 lineWithoutComments = lineWithoutComments.split(Pattern.quote(CODE_COMMENT_PREFIX))[0]; |
|
1069 } |
|
1070 |
|
1071 /** |
|
1072 * If this (searchForMethodDefinition) is true, the method assumes that |
|
1073 * it has encountered a line with the method name but not sure whether |
|
1074 * its a definition point or invocation point. So, it scans for the text |
|
1075 * after the method name until it encounters certain delimiters, to conclude |
|
1076 * whether its point of definition or point of invocation. |
|
1077 */ |
|
1078 if(searchForMethodDefinition) |
|
1079 { |
|
1080 String neededText = fetchContentBeforeDefinition(lineWithoutComments); |
|
1081 tmpBuffer.append(neededText); |
|
1082 |
|
1083 if(hasDelimiter(tmpBuffer.toString())) |
|
1084 { |
|
1085 tmpBuffer = tmpBuffer.deleteCharAt(tmpBuffer.length()-1); |
|
1086 String contentToBeParsed = tmpBuffer.toString(); |
|
1087 boolean isMethodDefined = parseForMethodDefinition(contentToBeParsed); |
|
1088 |
|
1089 if(isMethodDefined) |
|
1090 { |
|
1091 searchForMethodDefinition = false; |
|
1092 wantedLine = methodStartingLine; |
|
1093 tmpBuffer = null; |
|
1094 break; |
|
1095 } |
|
1096 else{ |
|
1097 searchForMethodDefinition = false; |
|
1098 tmpBuffer = null; |
|
1099 continue; |
|
1100 } |
|
1101 } |
|
1102 } |
|
1103 // |
|
1104 //Now we know that this line where we are, is not inside of "/**/" -comments, |
|
1105 //This line is not a comment line with "//":s |
|
1106 //And this line is containing method name |
|
1107 // |
|
1108 |
|
1109 //If component is DLL it exports functions, and EXPORT_C (or IMPORT_C just in case) must occur in line |
|
1110 //This is not a perfect way to do it, but it works, because EXPORT_C definition is |
|
1111 //most likely written to same line as method definition. |
|
1112 if (isDll && |
|
1113 ( lineWithoutComments.toUpperCase().indexOf(EXPORT) != SourceFileLocation.OFFSET_NOT_FOUND |
|
1114 || lineWithoutComments.toUpperCase().indexOf(IMPORT) != SourceFileLocation.OFFSET_NOT_FOUND) |
|
1115 && lineWithoutComments.indexOf(SEMI_COLON) == SourceFileLocation.OFFSET_NOT_FOUND) { |
|
1116 wantedLine = aLine; |
|
1117 break; |
|
1118 } |
|
1119 //If the line contains function name but does not contain EXPORT_C or IMPORT_C, we will |
|
1120 //scan the text after method name to check if method definition has started. |
|
1121 else if(isDll && lineWithoutComments.contains(methodName)) { |
|
1122 tmpBuffer = new StringBuffer(); |
|
1123 tmpBuffer.append(lineWithoutComments.substring(lineWithoutComments.indexOf(methodName) + methodName.length())); |
|
1124 |
|
1125 methodStartingLine = aLine; |
|
1126 searchForMethodDefinition = true; |
|
1127 } |
|
1128 //If method name is not [ClassName]::[MethodName] but e.g. __my_macro, excluding EXPORT_C check |
|
1129 //But then there must be "(" |
|
1130 else if(methodName.indexOf(CLASS_SEPARATOR) == SourceFileLocation.OFFSET_NOT_FOUND |
|
1131 && lineWithoutComments.indexOf(SEMI_COLON) == SourceFileLocation.OFFSET_NOT_FOUND |
|
1132 && lineWithoutComments.indexOf(METHOD_OPENING_CHAR) != SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1133 wantedLine = aLine; |
|
1134 break; |
|
1135 } |
|
1136 |
|
1137 //If its not dll but exe, it does not export functions, then it might be implementation |
|
1138 else if(!isDll && lineWithoutComments.indexOf(SEMI_COLON) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1139 wantedLine = aLine; |
|
1140 break; |
|
1141 } |
|
1142 //Else we are not interested on this line and keep seeking |
|
1143 else{ |
|
1144 printUtility.println( |
|
1145 Messages.getString("MapSourceFinder.OffsetSeek_Msg_Part_1") //$NON-NLS-1$ |
|
1146 +methodName |
|
1147 +Messages.getString("MapSourceFinder.OffsetSeek_Msg_Part_2") //$NON-NLS-1$ |
|
1148 +file.getAbsolutePath() |
|
1149 +Messages.getString("MapSourceFinder.OffsetSeek_Msg_Part_3")//$NON-NLS-1$ |
|
1150 +lineWithoutComments |
|
1151 +Messages.getString("MapSourceFinder.OffsetSeek_Msg_Part_4")); //$NON-NLS-1$ |
|
1152 } |
|
1153 |
|
1154 }//for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) { |
|
1155 if(wantedLine != null){ |
|
1156 offset = fileBuffer.lastIndexOf(wantedLine); //getOfsetForLine(lines, wantedLine); |
|
1157 } |
|
1158 |
|
1159 }//if (lines.size() > 0) { |
|
1160 |
|
1161 //Now wantedLine should be line we want, we can found out offset for that line |
|
1162 |
|
1163 return offset; |
|
1164 } |
|
1165 |
|
1166 /** |
|
1167 * Get content of this line with out comments. |
|
1168 * e.g. 'MyClass::Foo(TInt bar /*My comments * /)' |
|
1169 * returns 'MyClass::Foo(TInt bar )' |
|
1170 * NOTE: does not handle '//' comments at all |
|
1171 * @param line Line to remove comments from |
|
1172 * @param isInsideCommentSegment set to <code>true</code>, if we are already are inside of comment segment |
|
1173 * @return a line without comments |
|
1174 */ |
|
1175 private String getLineWithOutComments(String line, boolean isInsideCommentSegment) { |
|
1176 |
|
1177 // /** aa */ BB /** cc */ DD --> Should return " BB DD" |
|
1178 // aa */ BB /** cc */ DD --> Should return " BB DD" if isInsideComment and "aa BB DD" if no |
|
1179 // AA */ should return "" if inside comments, and "AA */" if not |
|
1180 |
|
1181 //if we are inside comments, and comment segment is not closing, |
|
1182 //there is no other than comments, so return empty string |
|
1183 if(isInsideCommentSegment && line.indexOf(COMMENT_END) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1184 return ""; //$NON-NLS-1$ |
|
1185 } |
|
1186 //if we are not inside comments and not even start a comment just return the line |
|
1187 else if(!isInsideCommentSegment && line.indexOf(COMMENT_START) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1188 return line; |
|
1189 } |
|
1190 //else we parse out everything else but comments |
|
1191 |
|
1192 StringBuffer b = new StringBuffer(); |
|
1193 String [] parts = line.split(Pattern.quote(COMMENT_START)); |
|
1194 |
|
1195 //Splitted string goes like this: |
|
1196 // "/** aa */ BB /** cc */ DD" --> |
|
1197 // " aa */ BB " |
|
1198 // " cc */ DD" |
|
1199 for (int i = 0; i < parts.length; i++) { |
|
1200 //Skip empty parts |
|
1201 if(parts[i].equals("")){ //$NON-NLS-1$ |
|
1202 continue; |
|
1203 } |
|
1204 //If we are not inside comments, and line was not started with comments, the first part belongs to text |
|
1205 else if(i==0 && !isInsideCommentSegment && parts[i].indexOf(COMMENT_END) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1206 b.append(parts[i]); |
|
1207 } |
|
1208 //if comment is opened, but not closed, this part belongs to comment and will be skipped |
|
1209 else if(parts[i].indexOf(COMMENT_END) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1210 continue; |
|
1211 }else{ |
|
1212 b.append(parts[i].substring( parts[i].indexOf(COMMENT_END)+COMMENT_END.length() ) ); |
|
1213 } |
|
1214 } |
|
1215 |
|
1216 return b.toString(); |
|
1217 } |
|
1218 /** |
|
1219 * Check if this line opens a comment segment, and is not closing it |
|
1220 * @param line Line to be checked. |
|
1221 * @return <code>true</code> if start a comment block without closing it, otherwise <code>false</code>. |
|
1222 */ |
|
1223 private boolean isLineOpeningCommentSegment(String line) { |
|
1224 |
|
1225 int commentStartIndex = line.lastIndexOf(COMMENT_START); |
|
1226 int commentEndIndex = line.lastIndexOf(COMMENT_END); |
|
1227 |
|
1228 if(commentStartIndex > commentEndIndex){ |
|
1229 return true; |
|
1230 } |
|
1231 |
|
1232 return false; |
|
1233 } |
|
1234 |
|
1235 /** |
|
1236 * Check if this line closes a comment segment |
|
1237 * @param line Line to be checked. |
|
1238 * @return <code>true</code> if line closes comment segment, otherwise <code>false</code>. |
|
1239 */ |
|
1240 private boolean isLineClosingCommentSegment(String line) { |
|
1241 |
|
1242 int commentStartIndex = line.lastIndexOf(COMMENT_START); |
|
1243 int commentEndIndex = line.lastIndexOf(COMMENT_END); |
|
1244 |
|
1245 if(commentEndIndex > commentStartIndex){ |
|
1246 return true; |
|
1247 } |
|
1248 |
|
1249 return false; |
|
1250 } |
|
1251 |
|
1252 |
|
1253 /** |
|
1254 * Check if this line is comment line starting with // |
|
1255 * @param line Line to be checked. |
|
1256 * @return <code>true</code> if line starts with //, otherwise <code>false</code>. |
|
1257 */ |
|
1258 private boolean isCommentLine(String line, String methodName) { |
|
1259 if(line.trim().startsWith(CODE_COMMENT_PREFIX)){ |
|
1260 return true; |
|
1261 } |
|
1262 else if(line.indexOf(CODE_COMMENT_PREFIX) != SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1263 |
|
1264 int commentIndex = line.indexOf(CODE_COMMENT_PREFIX); |
|
1265 int methodNameIndex = line.indexOf(methodName); |
|
1266 if(commentIndex > methodNameIndex){ |
|
1267 return false; |
|
1268 }else{ |
|
1269 return true; |
|
1270 } |
|
1271 }else{ |
|
1272 return false; |
|
1273 } |
|
1274 } |
|
1275 |
|
1276 /** |
|
1277 * Gets *.map file path. |
|
1278 * @param componentName Component name. |
|
1279 * @param variant Build variant. |
|
1280 * @param build Build type (urel/udeb). |
|
1281 * @param epocRootPath EPOCROOT path. |
|
1282 * @return path to .dll file +MAP_FILE_SUFFIX |
|
1283 */ |
|
1284 private String getMapFilePath(String componentName, String variant, String build, |
|
1285 String epocRootPath) { |
|
1286 String mapPath = |
|
1287 epocRootPath + File.separatorChar |
|
1288 +SourceFileLocation.EPOC32_FOLDER_NAME + File.separatorChar |
|
1289 +SourceFileLocation.RELEASE_FOLDER_NAME + File.separatorChar |
|
1290 +variant + File.separatorChar |
|
1291 +build + File.separatorChar |
|
1292 +componentName |
|
1293 +MAP_FILE_SUFFIX; |
|
1294 mapPath = makeWindowsPath(mapPath); |
|
1295 return mapPath; |
|
1296 } |
|
1297 |
|
1298 /* (non-Javadoc) |
|
1299 * @see com.nokia.s60tools.util.sourcecode.ISourcesFinder#findSourceFiles(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) |
|
1300 */ |
|
1301 public String[] findSourceFiles(String componentName, |
|
1302 String variant, String build, String epocRootPath |
|
1303 ) throws CannotFoundFileException { |
|
1304 |
|
1305 try { |
|
1306 //Projects map file |
|
1307 String mapFilePath = getMapFilePath(componentName, variant, build, epocRootPath); |
|
1308 File mapFile = getMapFile(mapFilePath); |
|
1309 |
|
1310 String objectFileName = componentName.split(Pattern.quote("."))[0]; //$NON-NLS-1$ |
|
1311 |
|
1312 //Get all source file paths from map file |
|
1313 String sourcePaths [] = getAllSourceFilePaths(mapFile, epocRootPath, objectFileName); |
|
1314 |
|
1315 return sourcePaths; |
|
1316 |
|
1317 } catch (FileNotFoundException e) { |
|
1318 e.printStackTrace(); |
|
1319 throw new CannotFoundFileException(e.getMessage() , e); |
|
1320 } catch (IOException e) { |
|
1321 e.printStackTrace(); |
|
1322 throw new CannotFoundFileException(e.getMessage() , e); |
|
1323 } catch (Exception e) { |
|
1324 e.printStackTrace(); |
|
1325 throw new CannotFoundFileException(e.getMessage() , e); |
|
1326 } |
|
1327 |
|
1328 } |
|
1329 |
|
1330 /* (non-Javadoc) |
|
1331 * @see com.nokia.s60tools.util.sourcecode.ISourcesFinder#findSourceFiles(java.lang.String, java.lang.String, java.util.Collection) |
|
1332 */ |
|
1333 public String[] findSourceFiles(String componentName, |
|
1334 String epocRootPath, Collection<String> pathsToSeekMapFile |
|
1335 ) throws CannotFoundFileException { |
|
1336 |
|
1337 try { |
|
1338 //Projects map file |
|
1339 String mapFileName = componentName + MAP_FILE_SUFFIX; |
|
1340 |
|
1341 File mapFile = getMapFile(pathsToSeekMapFile, componentName, mapFileName); |
|
1342 |
|
1343 //If we did not found map file, we cannot proceed to src file seek |
|
1344 if(mapFile == null){ |
|
1345 String msg = "'" + mapFileName //$NON-NLS-1$ |
|
1346 +"' " //$NON-NLS-1$ |
|
1347 +Messages.getString("MapSourceFinder.MapFileNotFoundForSource_ErrMsg_Part1") //$NON-NLS-1$ |
|
1348 +componentName; |
|
1349 String consoleMsg = msg + " " //$NON-NLS-1$ |
|
1350 +Messages.getString("MapSourceFinder.MapFileNotFoundForSource_ErrMsg_Part2"); //$NON-NLS-1$ |
|
1351 |
|
1352 String pathSeparator= ", "; //$NON-NLS-1$ |
|
1353 for (Iterator<String> iterator = pathsToSeekMapFile.iterator(); iterator |
|
1354 .hasNext();) { |
|
1355 String path = (String) iterator.next(); |
|
1356 consoleMsg += path + pathSeparator; |
|
1357 } |
|
1358 consoleMsg = consoleMsg.substring(0, consoleMsg.length() - pathSeparator.length()); |
|
1359 printUtility.println(consoleMsg, IConsolePrintUtility.MSG_ERROR); |
|
1360 throw new CannotFoundFileException(msg); |
|
1361 } |
|
1362 String objectFileName = componentName.split(Pattern.quote("."))[0]; //$NON-NLS-1$ |
|
1363 |
|
1364 //Get all source file paths from map file |
|
1365 String sourcePaths [] = getAllSourceFilePaths(mapFile, epocRootPath, objectFileName); |
|
1366 |
|
1367 return sourcePaths; |
|
1368 |
|
1369 } catch (FileNotFoundException e) { |
|
1370 e.printStackTrace(); |
|
1371 throw new CannotFoundFileException(e.getMessage() , e); |
|
1372 } catch (IOException e) { |
|
1373 e.printStackTrace(); |
|
1374 throw new CannotFoundFileException(e.getMessage() , e); |
|
1375 } catch (Exception e) { |
|
1376 e.printStackTrace(); |
|
1377 throw new CannotFoundFileException(e.getMessage() , e); |
|
1378 } |
|
1379 |
|
1380 } |
|
1381 /** |
|
1382 * Get all source file lines from given file. |
|
1383 * @param file File object to be checked for. |
|
1384 * @param epocRootPath EPOCROOT path. |
|
1385 * @param objectFileName Object file name used to filter results. |
|
1386 * @return all source file lines from given file. |
|
1387 * @throws IOException |
|
1388 */ |
|
1389 private String[] getAllSourceFilePaths(File file, String epocRootPath, String objectFileName) throws IOException { |
|
1390 |
|
1391 FileInputStream in = null; |
|
1392 InputStreamReader isr = null; |
|
1393 BufferedReader br = null; |
|
1394 //HashSet does not allow duplicates |
|
1395 HashSet<String> sourceFilePaths = new HashSet<String>(); |
|
1396 |
|
1397 try { |
|
1398 in = new FileInputStream(file); |
|
1399 isr = new InputStreamReader(in); |
|
1400 br = new BufferedReader(isr); |
|
1401 |
|
1402 String line = null; |
|
1403 |
|
1404 // seek wanted text from file line by line |
|
1405 while ((line = br.readLine()) != null) { |
|
1406 // if we found wanted text, stopping search |
|
1407 String srcLine = isSourceFilePathLine(line, epocRootPath, objectFileName); |
|
1408 if (srcLine != null) { |
|
1409 sourceFilePaths.add(srcLine); |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 } finally { |
|
1414 if (in != null) { |
|
1415 in.close(); |
|
1416 } |
|
1417 if (isr != null) { |
|
1418 isr.close(); |
|
1419 } |
|
1420 if (br != null) { |
|
1421 br.close(); |
|
1422 } |
|
1423 } |
|
1424 |
|
1425 return (String []) sourceFilePaths.toArray(new String [0]); |
|
1426 } |
|
1427 |
|
1428 /** |
|
1429 * Check if line from file is a source file line or not. |
|
1430 * @param line Line to be checked. |
|
1431 * @param epocRootPath EPOCROOT path. |
|
1432 * @param objectFileName Object file name used to filter results. |
|
1433 * @return Path to src file or <code>null</code> if it was not src line. |
|
1434 */ |
|
1435 private String isSourceFilePathLine(String line, String epocRootPath, String objectFileName) { |
|
1436 |
|
1437 // * Source file lines are e.g. lines: |
|
1438 // * \s60\mw\web\WebEngine\OssWebengine\WebCore\kwq\kwqvariant.cpp 0x00000000 Number 0 KWQVariant.o ABSOLUTE |
|
1439 // * \src\cedar\generic\base\e32\EUSER\EPOC\ up_dll_file.cpp 0x00000000 Number 0 up_dll_file.o ABSOLUTE |
|
1440 // * \\src\\cedar\\generic\\BASE\\E32\\compsupp\\RVCT2_2\\ucppinit_aeabi.cpp 0x00000000 Number 0 ucppinit_aeabi.o ABSOLUTE |
|
1441 |
|
1442 // * but not lines: |
|
1443 // * \EPOC32\BUILD\src\COMMON\GENERIC\comms-infras\esock\group\ESOCK\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE |
|
1444 // * \EPOC32\BUILD\src\cedar\generic\base\e32\EDLL\ARMV5\ urel\ uc_dll_.cpp 0x00000000 Number 0 uc_dll_.o ABSOLUTE |
|
1445 // * \\EPOC32\\BUILD\\src\\cedar\\generic\\base\\e32\\EDLL\\ARMV5\\urel\\uc_dll_.cpp 0x00000000 Number 0 uc_dll_.o ABSOLUTE |
|
1446 |
|
1447 // Also source codes can be from users own source projects, e.g. |
|
1448 // \Projects\Trombi\Carbide\creator\src\creatormailboxelement.cpp 0x00000000 Number 0 creator.in ABSOLUTE |
|
1449 |
|
1450 if(line == null || line.trim().length() < 1){ |
|
1451 return null; |
|
1452 } |
|
1453 |
|
1454 if( (line.contains(CPP_SUFFIX) || line.contains(C_SUFFIX) )&& |
|
1455 line.contains(NULL_ADDRESS) && |
|
1456 line.contains(ABSOLUTE) && |
|
1457 line.toLowerCase().contains(objectFileName.toLowerCase())){ |
|
1458 |
|
1459 //if we found wanted text, checking that it does not contain |
|
1460 //\EPOC32\BUILD or \\EPOC32\\BUILD, because then its not a source, but build file |
|
1461 //fixing slashes so we can find epoc32 build folder in any cases. |
|
1462 String srcPath = line.replace("/", BACKSLASH).trim(); //$NON-NLS-1$ //$NON-NLS-2$ |
|
1463 //removing multiple spaces: " +" means more than one white spaces, e.g. "a b c" -> "a b c" |
|
1464 |
|
1465 //Making sure that souce location does not point to BUILD folder |
|
1466 if(srcPath.indexOf(EPOC32_BUILD) == SourceFileLocation.OFFSET_NOT_FOUND |
|
1467 && srcPath.indexOf(EPOC32_BUILD_DOUBLE_SLASHES) == SourceFileLocation.OFFSET_NOT_FOUND){ |
|
1468 |
|
1469 if(!srcPath.startsWith(BACKSLASH)){ |
|
1470 srcPath = BACKSLASH + srcPath; |
|
1471 } |
|
1472 |
|
1473 //if path starts with src\... or s60\... its a symbian or S60 src path |
|
1474 if(srcPath.startsWith( SRC_PATH_PREFIX) || srcPath.startsWith( S60_PATH_PREFIX) |
|
1475 || srcPath.startsWith( SRC_PATH_PREFIX_DOUBLE_SLASHS) || srcPath.startsWith( S60_PATH_PREFIX_DOUBLE_SLASHS) |
|
1476 ) |
|
1477 { |
|
1478 |
|
1479 String srcPathOrig = srcPath.substring(0, srcPath.indexOf(NULL_ADDRESS)).trim(); |
|
1480 srcPath = epocRootPath + srcPathOrig; |
|
1481 srcPath = makeWindowsPath(srcPath); |
|
1482 // Making sure that path does not have duplicate EPOCROOT. |
|
1483 File file = stripEpocRootFromPath(srcPathOrig, epocRootPath, new File(srcPath)); |
|
1484 return file.getAbsolutePath(); |
|
1485 } |
|
1486 //otherwise it can be users own source codes from own projects, and path can be anything |
|
1487 //then cheking that found source file path is actually real path to existing file |
|
1488 else{ |
|
1489 String srcPathOrig = srcPath.substring(0, srcPath.indexOf(NULL_ADDRESS)).trim(); |
|
1490 srcPath = epocRootPath + srcPathOrig; |
|
1491 srcPath = makeWindowsPath(srcPath); |
|
1492 // Making sure that path does not have duplicate EPOCROOT. |
|
1493 File file = stripEpocRootFromPath(srcPathOrig, epocRootPath, new File(srcPath)); |
|
1494 if(file.exists()){ |
|
1495 return file.getAbsolutePath(); |
|
1496 } |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 } |
|
1501 |
|
1502 return null; |
|
1503 } |
|
1504 |
|
1505 /** |
|
1506 * The method parses the given content for certain characters in a specific order |
|
1507 * to determine whether method definition has started or not. |
|
1508 * @param lineContent content to be parsed. |
|
1509 * @return true if the method definition is started else false. |
|
1510 */ |
|
1511 private boolean parseForMethodDefinition(String lineContent) |
|
1512 { |
|
1513 Stack<Character> chars_stack = new Stack<Character>(); |
|
1514 char [] line_chars = lineContent.toCharArray(); |
|
1515 |
|
1516 final char METHOD_OPENING_CHAR = '('; |
|
1517 final char METHOD_CLOSING_CHAR = ')'; |
|
1518 final char METHOD_DEFINITION_OPENING_CHAR = '{'; |
|
1519 |
|
1520 for(char c: line_chars) |
|
1521 { |
|
1522 switch(c){ |
|
1523 case METHOD_OPENING_CHAR: |
|
1524 case METHOD_CLOSING_CHAR: |
|
1525 case METHOD_DEFINITION_OPENING_CHAR: |
|
1526 chars_stack.push(c); |
|
1527 break; |
|
1528 } |
|
1529 } |
|
1530 |
|
1531 while(!chars_stack.isEmpty()) |
|
1532 { |
|
1533 Character lastChar = chars_stack.pop(); |
|
1534 |
|
1535 if(lastChar == METHOD_DEFINITION_OPENING_CHAR) |
|
1536 { |
|
1537 char prevChar_1 = chars_stack.pop(); |
|
1538 char prevChar_2 = chars_stack.pop(); |
|
1539 |
|
1540 if((prevChar_1 == METHOD_CLOSING_CHAR) && (prevChar_2 == METHOD_OPENING_CHAR)) |
|
1541 return true; |
|
1542 } |
|
1543 } |
|
1544 return false; |
|
1545 |
|
1546 } |
|
1547 |
|
1548 /** |
|
1549 * The method checks for some predefined delimiter characters and |
|
1550 * returns the content before those characters. |
|
1551 * @param input |
|
1552 * @return |
|
1553 */ |
|
1554 private String fetchContentBeforeDefinition(String input) |
|
1555 { |
|
1556 if(input.contains(SEMI_COLON)) |
|
1557 { |
|
1558 if(input.contains(METHOD_DEFINITION_CLOSING_CHAR) |
|
1559 && input.indexOf(METHOD_DEFINITION_CLOSING_CHAR) < input.indexOf(SEMI_COLON)) |
|
1560 return input.substring(0, input.indexOf(METHOD_DEFINITION_CLOSING_CHAR) +1); |
|
1561 else |
|
1562 return input.substring(0, input.indexOf(SEMI_COLON) +1); |
|
1563 } |
|
1564 else if(input.contains(METHOD_DEFINITION_CLOSING_CHAR)){ |
|
1565 return input.substring(0, input.indexOf(METHOD_DEFINITION_CLOSING_CHAR) +1); |
|
1566 } |
|
1567 else{ |
|
1568 return input.toString(); |
|
1569 } |
|
1570 } |
|
1571 |
|
1572 private boolean hasDelimiter(String line) |
|
1573 { |
|
1574 if(line.contains(METHOD_DEFINITION_CLOSING_CHAR) || |
|
1575 line.contains(SEMI_COLON)) |
|
1576 return true; |
|
1577 else |
|
1578 return false; |
|
1579 } |
|
1580 |
|
1581 } |