]>
Commit | Line | Data |
---|---|---|
878ddf1f | 1 | /*\r |
2 | * \r | |
3 | * Copyright 2001-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 | |
17 | package net.sf.antcontrib.cpptasks;\r | |
18 | import java.io.File;\r | |
19 | import java.io.IOException;\r | |
20 | import java.util.Enumeration;\r | |
21 | import java.util.Hashtable;\r | |
22 | import java.util.StringTokenizer;\r | |
23 | import java.util.Vector;\r | |
24 | \r | |
25 | import org.apache.tools.ant.BuildException;\r | |
26 | import org.apache.tools.ant.Project;\r | |
27 | import org.apache.tools.ant.taskdefs.Execute;\r | |
28 | import org.apache.tools.ant.taskdefs.LogStreamHandler;\r | |
29 | import org.apache.tools.ant.types.Commandline;\r | |
30 | import org.apache.tools.ant.types.Environment;\r | |
31 | /**\r | |
32 | * Some utilities used by the CC and Link tasks.\r | |
33 | * \r | |
34 | * @author Adam Murdoch\r | |
35 | */\r | |
36 | public class CUtil {\r | |
37 | /**\r | |
38 | * A class that splits a white-space, comma-separated list into a String\r | |
39 | * array. Used for task attributes.\r | |
40 | */\r | |
41 | public static final class StringArrayBuilder {\r | |
42 | private String[] _value;\r | |
43 | public StringArrayBuilder(String value) {\r | |
44 | // Split the defines up\r | |
45 | StringTokenizer tokens = new StringTokenizer(value, ", ");\r | |
46 | Vector vallist = new Vector();\r | |
47 | while (tokens.hasMoreTokens()) {\r | |
48 | String val = tokens.nextToken().trim();\r | |
49 | if (val.length() == 0) {\r | |
50 | continue;\r | |
51 | }\r | |
52 | vallist.addElement(val);\r | |
53 | }\r | |
54 | _value = new String[vallist.size()];\r | |
55 | vallist.copyInto(_value);\r | |
56 | }\r | |
57 | public String[] getValue() {\r | |
58 | return _value;\r | |
59 | }\r | |
60 | }\r | |
61 | /**\r | |
62 | * Adds the elements of the array to the given vector\r | |
63 | */\r | |
64 | public static void addAll(Vector dest, Object[] src) {\r | |
65 | if (src == null) {\r | |
66 | return;\r | |
67 | }\r | |
68 | for (int i = 0; i < src.length; i++) {\r | |
69 | dest.addElement(src[i]);\r | |
70 | }\r | |
71 | }\r | |
72 | /**\r | |
73 | * Checks a array of names for non existent or non directory entries and\r | |
74 | * nulls them out.\r | |
75 | * \r | |
76 | * @return Count of non-null elements\r | |
77 | */\r | |
78 | public static int checkDirectoryArray(String[] names) {\r | |
79 | int count = 0;\r | |
80 | for (int i = 0; i < names.length; i++) {\r | |
81 | if (names[i] != null) {\r | |
82 | File dir = new File(names[i]);\r | |
83 | if (dir.exists() && dir.isDirectory()) {\r | |
84 | count++;\r | |
85 | } else {\r | |
86 | names[i] = null;\r | |
87 | }\r | |
88 | }\r | |
89 | }\r | |
90 | return count;\r | |
91 | }\r | |
92 | /**\r | |
93 | * Extracts the basename of a file, removing the extension, if present\r | |
94 | */\r | |
95 | public static String getBasename(File file) {\r | |
96 | String path = file.getPath();\r | |
97 | // Remove the extension\r | |
98 | String basename = file.getName();\r | |
99 | int pos = basename.lastIndexOf('.');\r | |
100 | if (pos != -1) {\r | |
101 | basename = basename.substring(0, pos);\r | |
102 | }\r | |
103 | return basename;\r | |
104 | }\r | |
105 | /**\r | |
106 | * Gets the parent directory for the executable file name using the current\r | |
107 | * directory and system executable path\r | |
108 | * \r | |
109 | * @param exeName\r | |
110 | * Name of executable such as "cl.exe"\r | |
111 | * @return parent directory or null if not located\r | |
112 | */\r | |
113 | public static File getExecutableLocation(String exeName) {\r | |
114 | //\r | |
115 | // must add current working directory to the\r | |
116 | // from of the path from the "path" environment variable\r | |
117 | File currentDir = new File(System.getProperty("user.dir"));\r | |
118 | if (new File(currentDir, exeName).exists()) {\r | |
119 | return currentDir;\r | |
120 | }\r | |
121 | File[] envPath = CUtil.getPathFromEnvironment("PATH",\r | |
122 | File.pathSeparator);\r | |
123 | for (int i = 0; i < envPath.length; i++) {\r | |
124 | if (new File(envPath[i], exeName).exists()) {\r | |
125 | return envPath[i];\r | |
126 | }\r | |
127 | }\r | |
128 | return null;\r | |
129 | }\r | |
130 | /**\r | |
131 | * Extracts the parent of a file\r | |
132 | */\r | |
133 | public static String getParentPath(String path) {\r | |
134 | int pos = path.lastIndexOf(File.separator);\r | |
135 | if (pos <= 0) {\r | |
136 | return null;\r | |
137 | }\r | |
138 | return path.substring(0, pos);\r | |
139 | }\r | |
140 | /**\r | |
141 | * Returns an array of File for each existing directory in the specified\r | |
142 | * environment variable\r | |
143 | * \r | |
144 | * @param envVariable\r | |
145 | * environment variable name such as "LIB" or "INCLUDE"\r | |
146 | * @param delim\r | |
147 | * delimitor used to separate parts of the path, typically ";"\r | |
148 | * or ":"\r | |
149 | * @return array of File's for each part that is an existing directory\r | |
150 | */\r | |
151 | public static File[] getPathFromEnvironment(String envVariable, String delim) {\r | |
152 | // OS/4000 does not support the env command.\r | |
153 | if (System.getProperty("os.name").equals("OS/400"))\r | |
154 | return new File[]{};\r | |
155 | Vector osEnv = Execute.getProcEnvironment();\r | |
156 | String match = envVariable.concat("=");\r | |
157 | for (Enumeration e = osEnv.elements(); e.hasMoreElements();) {\r | |
158 | String entry = ((String) e.nextElement()).trim();\r | |
159 | if (entry.length() > match.length()) {\r | |
160 | String entryFrag = entry.substring(0, match.length());\r | |
161 | if (entryFrag.equalsIgnoreCase(match)) {\r | |
162 | String path = entry.substring(match.length());\r | |
163 | return parsePath(path, delim);\r | |
164 | }\r | |
165 | }\r | |
166 | }\r | |
167 | File[] noPath = new File[0];\r | |
168 | return noPath;\r | |
169 | }\r | |
170 | /**\r | |
171 | * Returns a relative path for the targetFile relative to the base\r | |
172 | * directory.\r | |
173 | * \r | |
174 | * @param canonicalBase\r | |
175 | * base directory as returned by File.getCanonicalPath()\r | |
176 | * @param targetFile\r | |
177 | * target file\r | |
178 | * @return relative path of target file. Returns targetFile if there were\r | |
179 | * no commonalities between the base and the target\r | |
180 | * \r | |
181 | * @author Curt Arnold\r | |
182 | */\r | |
183 | public static String getRelativePath(String base, File targetFile) {\r | |
184 | try {\r | |
185 | //\r | |
186 | // remove trailing file separator\r | |
187 | //\r | |
188 | String canonicalBase = base;\r | |
189 | if (base.charAt(base.length() - 1) == File.separatorChar) {\r | |
190 | canonicalBase = base.substring(0, base.length() - 1);\r | |
191 | }\r | |
192 | //\r | |
193 | // get canonical name of target and remove trailing separator\r | |
194 | //\r | |
195 | String canonicalTarget;\r | |
196 | if (System.getProperty("os.name").equals("OS/400"))\r | |
197 | canonicalTarget = targetFile.getPath();\r | |
198 | else\r | |
199 | canonicalTarget = targetFile.getCanonicalPath();\r | |
200 | if (canonicalTarget.charAt(canonicalTarget.length() - 1) == File.separatorChar) {\r | |
201 | canonicalTarget = canonicalTarget.substring(0, canonicalTarget\r | |
202 | .length() - 1);\r | |
203 | }\r | |
204 | if (canonicalTarget.equals(canonicalBase)) {\r | |
205 | return ".";\r | |
206 | }\r | |
207 | //\r | |
208 | // see if the prefixes are the same\r | |
209 | //\r | |
210 | if (canonicalBase.substring(0, 2).equals("\\\\")) {\r | |
211 | //\r | |
212 | // UNC file name, if target file doesn't also start with same\r | |
213 | // server name, don't go there\r | |
214 | int endPrefix = canonicalBase.indexOf('\\', 2);\r | |
215 | String prefix1 = canonicalBase.substring(0, endPrefix);\r | |
216 | String prefix2 = canonicalTarget.substring(0, endPrefix);\r | |
217 | if (!prefix1.equals(prefix2)) {\r | |
218 | return canonicalTarget;\r | |
219 | }\r | |
220 | } else {\r | |
221 | if (canonicalBase.substring(1, 3).equals(":\\")) {\r | |
222 | int endPrefix = 2;\r | |
223 | String prefix1 = canonicalBase.substring(0, endPrefix);\r | |
224 | String prefix2 = canonicalTarget.substring(0, endPrefix);\r | |
225 | if (!prefix1.equals(prefix2)) {\r | |
226 | return canonicalTarget;\r | |
227 | }\r | |
228 | } else {\r | |
229 | if (canonicalBase.charAt(0) == '/') {\r | |
230 | if (canonicalTarget.charAt(0) != '/') {\r | |
231 | return canonicalTarget;\r | |
232 | }\r | |
233 | }\r | |
234 | }\r | |
235 | }\r | |
236 | char separator = File.separatorChar;\r | |
237 | int lastSeparator = -1;\r | |
238 | int minLength = canonicalBase.length();\r | |
239 | if (canonicalTarget.length() < minLength) {\r | |
240 | minLength = canonicalTarget.length();\r | |
241 | }\r | |
242 | int firstDifference = minLength + 1;\r | |
243 | //\r | |
244 | // walk to the shorter of the two paths\r | |
245 | // finding the last separator they have in common\r | |
246 | for (int i = 0; i < minLength; i++) {\r | |
247 | if (canonicalTarget.charAt(i) == canonicalBase.charAt(i)) {\r | |
248 | if (canonicalTarget.charAt(i) == separator) {\r | |
249 | lastSeparator = i;\r | |
250 | }\r | |
251 | } else {\r | |
252 | firstDifference = lastSeparator + 1;\r | |
253 | break;\r | |
254 | }\r | |
255 | }\r | |
256 | StringBuffer relativePath = new StringBuffer(50);\r | |
257 | //\r | |
258 | // walk from the first difference to the end of the base\r | |
259 | // adding "../" for each separator encountered\r | |
260 | //\r | |
261 | if (canonicalBase.length() > firstDifference) {\r | |
262 | relativePath.append("..");\r | |
263 | for (int i = firstDifference; i < canonicalBase.length(); i++) {\r | |
264 | if (canonicalBase.charAt(i) == separator) {\r | |
265 | relativePath.append(separator);\r | |
266 | relativePath.append("..");\r | |
267 | }\r | |
268 | }\r | |
269 | }\r | |
270 | if (canonicalTarget.length() > firstDifference) {\r | |
271 | //\r | |
272 | // append the rest of the target\r | |
273 | //\r | |
274 | //\r | |
275 | if (relativePath.length() > 0) {\r | |
276 | relativePath.append(separator);\r | |
277 | }\r | |
278 | relativePath.append(canonicalTarget.substring(firstDifference));\r | |
279 | }\r | |
280 | return relativePath.toString();\r | |
281 | } catch (IOException ex) {\r | |
282 | }\r | |
283 | return targetFile.toString();\r | |
284 | }\r | |
285 | public static boolean isActive(Project p, String ifCond, String unlessCond)\r | |
286 | throws BuildException {\r | |
287 | if (ifCond != null) {\r | |
288 | String ifValue = p.getProperty(ifCond);\r | |
289 | if (ifValue == null) {\r | |
290 | return false;\r | |
291 | } else {\r | |
292 | if (ifValue.equals("false") || ifValue.equals("no")) {\r | |
293 | throw new BuildException("if condition \"" + ifCond\r | |
294 | + "\" has suspicious value \"" + ifValue);\r | |
295 | }\r | |
296 | }\r | |
297 | }\r | |
298 | if (unlessCond != null) {\r | |
299 | String unlessValue = p.getProperty(unlessCond);\r | |
300 | if (unlessValue != null) {\r | |
301 | if (unlessValue.equals("false") || unlessValue.equals("no")) {\r | |
302 | throw new BuildException("unless condition \"" + unlessCond\r | |
303 | + "\" has suspicious value \"" + unlessValue);\r | |
304 | }\r | |
305 | return false;\r | |
306 | }\r | |
307 | }\r | |
308 | return true;\r | |
309 | }\r | |
310 | /**\r | |
311 | * Parse a string containing directories into an File[]\r | |
312 | * \r | |
313 | * @param path\r | |
314 | * path string, for example ".;c:\something\include"\r | |
315 | * @param delim\r | |
316 | * delimiter, typically ; or :\r | |
317 | */\r | |
318 | public static File[] parsePath(String path, String delim) {\r | |
319 | Vector libpaths = new Vector();\r | |
320 | int delimPos = 0;\r | |
321 | for (int startPos = 0; startPos < path.length(); startPos = delimPos\r | |
322 | + delim.length()) {\r | |
323 | delimPos = path.indexOf(delim, startPos);\r | |
324 | if (delimPos < 0) {\r | |
325 | delimPos = path.length();\r | |
326 | }\r | |
327 | //\r | |
328 | // don't add an entry for zero-length paths\r | |
329 | //\r | |
330 | if (delimPos > startPos) {\r | |
331 | String dirName = path.substring(startPos, delimPos);\r | |
332 | File dir = new File(dirName);\r | |
333 | if (dir.exists() && dir.isDirectory()) {\r | |
334 | libpaths.addElement(dir);\r | |
335 | }\r | |
336 | }\r | |
337 | }\r | |
338 | File[] paths = new File[libpaths.size()];\r | |
339 | libpaths.copyInto(paths);\r | |
340 | return paths;\r | |
341 | }\r | |
342 | /**\r | |
343 | * This method is exposed so test classes can overload and test the\r | |
344 | * arguments without actually spawning the compiler\r | |
345 | */\r | |
346 | public static int runCommand(CCTask task, File workingDir,\r | |
347 | String[] cmdline, boolean newEnvironment, Environment env)\r | |
348 | throws BuildException {\r | |
349 | try {\r | |
350 | task.log(Commandline.toString(cmdline), Project.MSG_VERBOSE);\r | |
351 | Execute exe = new Execute(new LogStreamHandler(task,\r | |
352 | Project.MSG_INFO, Project.MSG_ERR));\r | |
353 | if (System.getProperty("os.name").equals("OS/390"))\r | |
354 | exe.setVMLauncher(false);\r | |
355 | exe.setAntRun(task.getProject());\r | |
356 | exe.setCommandline(cmdline);\r | |
357 | exe.setWorkingDirectory(workingDir);\r | |
358 | if (env != null) {\r | |
359 | String[] environment = env.getVariables();\r | |
360 | if (environment != null) {\r | |
361 | for (int i = 0; i < environment.length; i++) {\r | |
362 | task.log("Setting environment variable: "\r | |
363 | + environment[i], Project.MSG_VERBOSE);\r | |
364 | }\r | |
365 | }\r | |
366 | exe.setEnvironment(environment);\r | |
367 | }\r | |
368 | exe.setNewenvironment(newEnvironment);\r | |
369 | return exe.execute();\r | |
370 | } catch (java.io.IOException exc) {\r | |
371 | throw new BuildException("Could not launch " + cmdline[0] + ": "\r | |
372 | + exc, task.getLocation());\r | |
373 | }\r | |
374 | }\r | |
375 | /**\r | |
376 | * Compares the contents of 2 arrays for equaliy.\r | |
377 | */\r | |
378 | public static boolean sameList(Object[] a, Object[] b) {\r | |
379 | if (a == null || b == null || a.length != b.length) {\r | |
380 | return false;\r | |
381 | }\r | |
382 | for (int i = 0; i < a.length; i++) {\r | |
383 | if (!a[i].equals(b[i])) {\r | |
384 | return false;\r | |
385 | }\r | |
386 | }\r | |
387 | return true;\r | |
388 | }\r | |
389 | /**\r | |
390 | * Compares the contents of an array and a Vector for equality.\r | |
391 | */\r | |
392 | public static boolean sameList(Vector v, Object[] a) {\r | |
393 | if (v == null || a == null || v.size() != a.length) {\r | |
394 | return false;\r | |
395 | }\r | |
396 | for (int i = 0; i < a.length; i++) {\r | |
397 | Object o = a[i];\r | |
398 | if (!o.equals(v.elementAt(i))) {\r | |
399 | return false;\r | |
400 | }\r | |
401 | }\r | |
402 | return true;\r | |
403 | }\r | |
404 | /**\r | |
405 | * Compares the contents of an array and a Vector for set equality. Assumes\r | |
406 | * input array and vector are sets (i.e. no duplicate entries)\r | |
407 | */\r | |
408 | public static boolean sameSet(Object[] a, Vector b) {\r | |
409 | if (a == null || b == null || a.length != b.size()) {\r | |
410 | return false;\r | |
411 | }\r | |
412 | if (a.length == 0) {\r | |
413 | return true;\r | |
414 | }\r | |
415 | // Convert the array into a set\r | |
416 | Hashtable t = new Hashtable();\r | |
417 | for (int i = 0; i < a.length; i++) {\r | |
418 | t.put(a[i], a[i]);\r | |
419 | }\r | |
420 | for (int i = 0; i < b.size(); i++) {\r | |
421 | Object o = b.elementAt(i);\r | |
422 | if (t.remove(o) == null) {\r | |
423 | return false;\r | |
424 | }\r | |
425 | }\r | |
426 | return (t.size() == 0);\r | |
427 | }\r | |
428 | /**\r | |
429 | * Converts a vector to a string array.\r | |
430 | */\r | |
431 | public static String[] toArray(Vector src) {\r | |
432 | String[] retval = new String[src.size()];\r | |
433 | src.copyInto(retval);\r | |
434 | return retval;\r | |
435 | }\r | |
436 | /**\r | |
437 | * Replaces any embedded quotes in the string so that the value can be\r | |
438 | * placed in an attribute in an XML file\r | |
439 | * \r | |
440 | * @param attrValue\r | |
441 | * value to be expressed\r | |
442 | * @return equivalent attribute literal\r | |
443 | * \r | |
444 | */\r | |
445 | public static String xmlAttribEncode(String attrValue) {\r | |
446 | int quotePos = attrValue.indexOf('\"');\r | |
447 | if (quotePos < 0) {\r | |
448 | return attrValue;\r | |
449 | }\r | |
450 | int startPos = 0;\r | |
451 | StringBuffer buf = new StringBuffer(attrValue.length() + 20);\r | |
452 | while (quotePos >= 0) {\r | |
453 | buf.append(attrValue.substring(startPos, quotePos));\r | |
454 | buf.append(""");\r | |
455 | startPos = quotePos + 1;\r | |
456 | quotePos = attrValue.indexOf('\"', startPos);\r | |
457 | }\r | |
458 | buf.append(attrValue.substring(startPos));\r | |
459 | return buf.toString();\r | |
460 | }\r | |
461 | }\r |