]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java
Initial import.
[mirror_edk2.git] / Tools / Source / Cpptasks / net / sf / antcontrib / cpptasks / compiler / AbstractCompiler.java
CommitLineData
878ddf1f 1/*\r
2 * \r
3 * Copyright 2002-2004 The Ant-Contrib project\r
4 *\r
5 * Licensed under the Apache License, Version 2.0 (the "License");\r
6 * you may not use this file except in compliance with the License.\r
7 * You may obtain a copy of the License at\r
8 *\r
9 * http://www.apache.org/licenses/LICENSE-2.0\r
10 *\r
11 * Unless required by applicable law or agreed to in writing, software\r
12 * distributed under the License is distributed on an "AS IS" BASIS,\r
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14 * See the License for the specific language governing permissions and\r
15 * limitations under the License.\r
16 */\r
17package net.sf.antcontrib.cpptasks.compiler;\r
18import java.io.BufferedReader;\r
19import java.io.File;\r
20import java.io.FileReader;\r
21import java.io.IOException;\r
22import java.io.Reader;\r
23import java.util.Vector;\r
24import net.sf.antcontrib.cpptasks.CCTask;\r
25import net.sf.antcontrib.cpptasks.CUtil;\r
26import net.sf.antcontrib.cpptasks.CompilerDef;\r
27import net.sf.antcontrib.cpptasks.DependencyInfo;\r
28import net.sf.antcontrib.cpptasks.ProcessorDef;\r
29import net.sf.antcontrib.cpptasks.parser.Parser;\r
30import net.sf.antcontrib.cpptasks.TargetDef;\r
31\r
32/**\r
33 * An abstract compiler implementation.\r
34 * \r
35 * @author Adam Murdoch\r
36 * @author Curt Arnold\r
37 */\r
38public abstract class AbstractCompiler extends AbstractProcessor\r
39 implements\r
40 Compiler {\r
41 private static final String[] emptyIncludeArray = new String[0];\r
42 private String outputSuffix;\r
43 protected AbstractCompiler(String[] sourceExtensions,\r
44 String[] headerExtensions, String outputSuffix) {\r
45 super(sourceExtensions, headerExtensions);\r
46 this.outputSuffix = outputSuffix;\r
47 }\r
48 /**\r
49 * Checks file name to see if parse should be attempted\r
50 * \r
51 * Default implementation returns false for files with extensions '.dll',\r
52 * 'tlb', '.res'\r
53 * \r
54 */\r
55 protected boolean canParse(File sourceFile) {\r
56 String sourceName = sourceFile.toString();\r
57 int lastPeriod = sourceName.lastIndexOf('.');\r
58 if (lastPeriod >= 0 && lastPeriod == sourceName.length() - 4) {\r
59 String ext = sourceName.substring(lastPeriod).toUpperCase();\r
60 if (ext.equals(".DLL") || ext.equals(".TLB") || ext.equals(".RES")) {\r
61 return false;\r
62 }\r
63 }\r
64 return true;\r
65 }\r
66 abstract protected CompilerConfiguration createConfiguration(CCTask task,\r
67 LinkType linkType, ProcessorDef[] baseConfigs,\r
68 CompilerDef specificConfig, TargetDef targetPlatform);\r
69 public ProcessorConfiguration createConfiguration(CCTask task,\r
70 LinkType linkType, ProcessorDef[] baseConfigs,\r
71 ProcessorDef specificConfig, TargetDef targetPlatform) {\r
72 if (specificConfig == null) {\r
73 throw new NullPointerException("specificConfig");\r
74 }\r
75 return createConfiguration(task, linkType, baseConfigs,\r
76 (CompilerDef) specificConfig, targetPlatform);\r
77 }\r
78 abstract protected Parser createParser(File sourceFile);\r
79 protected String getBaseOutputName(String inputFile) {\r
80 int lastSlash = inputFile.lastIndexOf('/');\r
81 int lastReverse = inputFile.lastIndexOf('\\');\r
82 int lastSep = inputFile.lastIndexOf(File.separatorChar);\r
83 if (lastReverse > lastSlash) {\r
84 lastSlash = lastReverse;\r
85 }\r
86 if (lastSep > lastSlash) {\r
87 lastSlash = lastSep;\r
88 }\r
89 int lastPeriod = inputFile.lastIndexOf('.');\r
90 if (lastPeriod < 0) {\r
91 lastPeriod = inputFile.length();\r
92 }\r
93 return inputFile.substring(lastSlash + 1, lastPeriod);\r
94 }\r
95 public String getOutputFileName(String inputFile) {\r
96 //\r
97 // if a recognized input file\r
98 //\r
99 if (bid(inputFile) > 1) {\r
100 String baseName = getBaseOutputName(inputFile);\r
101 return baseName + outputSuffix;\r
102 }\r
103 return null;\r
104 }\r
105 /**\r
106 * Returns dependency info for the specified source file\r
107 * \r
108 * @param task\r
109 * task for any diagnostic output\r
110 * @param source\r
111 * file to be parsed\r
112 * @param includePath\r
113 * include path to be used to resolve included files\r
114 * \r
115 * @param sysIncludePath\r
116 * sysinclude path from build file, files resolved using\r
117 * sysInclude path will not participate in dependency analysis\r
118 * \r
119 * @param envIncludePath\r
120 * include path from environment variable, files resolved with\r
121 * envIncludePath will not participate in dependency analysis\r
122 * \r
123 * @param baseDir\r
124 * used to produce relative paths in DependencyInfo\r
125 * @param includePathIdentifier\r
126 * used to distinguish DependencyInfo's from different include\r
127 * path settings\r
128 * \r
129 * @author Curt Arnold\r
130 */\r
131 public final DependencyInfo parseIncludes(CCTask task, File source,\r
132 File[] includePath, File[] sysIncludePath, File[] envIncludePath,\r
133 File baseDir, String includePathIdentifier) {\r
134 //\r
135 // if any of the include files can not be identified\r
136 // change the sourceLastModified to Long.MAX_VALUE to\r
137 // force recompilation of anything that depends on it\r
138 long sourceLastModified = source.lastModified();\r
139 File[] sourcePath = new File[1];\r
140 sourcePath[0] = new File(source.getParent());\r
141 Vector onIncludePath = new Vector();\r
142 Vector onSysIncludePath = new Vector();\r
143 String baseDirPath;\r
144 try {\r
145 baseDirPath = baseDir.getCanonicalPath();\r
146 } catch (IOException ex) {\r
147 baseDirPath = baseDir.toString();\r
148 }\r
149 String relativeSource = CUtil.getRelativePath(baseDirPath, source);\r
150 String[] includes = emptyIncludeArray;\r
151 if (canParse(source)) {\r
152 Parser parser = createParser(source);\r
153 try {\r
154 Reader reader = new BufferedReader(new FileReader(source));\r
155 parser.parse(reader);\r
156 includes = parser.getIncludes();\r
157 } catch (IOException ex) {\r
158 task.log("Error parsing " + source.toString() + ":"\r
159 + ex.toString());\r
160 includes = new String[0];\r
161 }\r
162 }\r
163 for (int i = 0; i < includes.length; i++) {\r
164 String includeName = includes[i];\r
165 if (!resolveInclude(includeName, sourcePath, onIncludePath)) {\r
166 if (!resolveInclude(includeName, includePath, onIncludePath)) {\r
167 if (!resolveInclude(includeName, sysIncludePath,\r
168 onSysIncludePath)) {\r
169 if (!resolveInclude(includeName, envIncludePath,\r
170 onSysIncludePath)) {\r
171 //\r
172 // this should be enough to require us to reparse\r
173 // the file with the missing include for dependency\r
174 // information without forcing a rebuild\r
175 sourceLastModified++;\r
176 }\r
177 }\r
178 }\r
179 }\r
180 }\r
181 for (int i = 0; i < onIncludePath.size(); i++) {\r
182 String relativeInclude = CUtil.getRelativePath(baseDirPath,\r
183 (File) onIncludePath.elementAt(i));\r
184 onIncludePath.setElementAt(relativeInclude, i);\r
185 }\r
186 for (int i = 0; i < onSysIncludePath.size(); i++) {\r
187 String relativeInclude = CUtil.getRelativePath(baseDirPath,\r
188 (File) onSysIncludePath.elementAt(i));\r
189 onSysIncludePath.setElementAt(relativeInclude, i);\r
190 }\r
191 return new DependencyInfo(includePathIdentifier, relativeSource,\r
192 sourceLastModified, onIncludePath, onSysIncludePath);\r
193 }\r
194 protected boolean resolveInclude(String includeName, File[] includePath,\r
195 Vector onThisPath) {\r
196 for (int i = 0; i < includePath.length; i++) {\r
197 File includeFile = new File(includePath[i], includeName);\r
198 if (includeFile.exists()) {\r
199 onThisPath.addElement(includeFile);\r
200 return true;\r
201 }\r
202 }\r
203 return false;\r
204 }\r
205}\r