View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar.cpptasks.gcc.cross.sparc_sun_solaris2;
21  
22  import java.io.BufferedReader;
23  import java.io.File;
24  import java.io.FileReader;
25  import java.io.IOException;
26  import java.util.Vector;
27  
28  import com.github.maven_nar.cpptasks.CUtil;
29  import com.github.maven_nar.cpptasks.compiler.CaptureStreamHandler;
30  import com.github.maven_nar.cpptasks.types.LibraryTypeEnum;
31  
32  /**
33   * A add-in class for Gcc processors
34   *
35   * 
36   */
37  public class GccProcessor {
38    // the results from gcc -dumpmachine
39    private static String machine;
40    private static String[] specs;
41    // the results from gcc -dumpversion
42    private static String version;
43  
44    private static int addLibraryPatterns(final String[] libnames, final StringBuffer buf, final String prefix,
45        final String extension, final String[] patterns, final int offset) {
46      for (int i = 0; i < libnames.length; i++) {
47        buf.setLength(0);
48        buf.append(prefix);
49        buf.append(libnames[i]);
50        buf.append(extension);
51        patterns[offset + i] = buf.toString();
52      }
53      return offset + libnames.length;
54    }
55  
56    /**
57     * Converts absolute Cygwin file or directory names to the corresponding
58     * Win32 name.
59     * 
60     * @param names
61     *          array of names, some elements may be null, will be changed in
62     *          place.
63     */
64    public static void convertCygwinFilenames(final String[] names) {
65      if (names == null) {
66        throw new NullPointerException("names");
67      }
68      final File gccDir = CUtil.getExecutableLocation(GccCCompiler.CMD_PREFIX + "gcc.exe");
69      if (gccDir != null) {
70        final String prefix = gccDir.getAbsolutePath() + "/..";
71        final StringBuffer buf = new StringBuffer();
72        for (int i = 0; i < names.length; i++) {
73          final String name = names[i];
74          if (name != null && name.length() > 1 && name.charAt(0) == '/') {
75            buf.setLength(0);
76            buf.append(prefix);
77            buf.append(name);
78            names[i] = buf.toString();
79          }
80        }
81      }
82    }
83  
84    public static String[] getLibraryPatterns(final String[] libnames, final LibraryTypeEnum libType) {
85      final StringBuffer buf = new StringBuffer();
86      final String[] patterns = new String[libnames.length * 2];
87      int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0);
88      if (isHPUX()) {
89        offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, offset);
90      } else {
91        offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, offset);
92      }
93      return patterns;
94    }
95  
96    public static String getMachine() {
97      if (machine == null) {
98        final String[] args = new String[] {
99            GccCCompiler.CMD_PREFIX + "gcc", "-dumpmachine"
100       };
101       final String[] cmdout = CaptureStreamHandler.run(args);
102       if (cmdout.length == 0) {
103         machine = "nomachine";
104       } else {
105         machine = cmdout[0];
106       }
107     }
108     return machine;
109   }
110 
111   public static String[] getOutputFileSwitch(final String letter, final String outputFile) {
112     final StringBuffer buf = new StringBuffer();
113     if (outputFile.indexOf(' ') >= 0) {
114       buf.append('"');
115       buf.append(outputFile.replace('\\', '/'));
116       buf.append('"');
117     } else {
118       buf.append(outputFile.replace('\\', '/'));
119     }
120     final String[] retval = new String[] {
121         letter, buf.toString()
122     };
123     return retval;
124   }
125 
126   /**
127    * Returns the contents of the gcc specs file.
128    * 
129    * The implementation locates gcc.exe in the executable path and then
130    * builds a relative path name from the results of -dumpmachine and
131    * -dumpversion. Attempts to use gcc -dumpspecs to provide this information
132    * resulted in stalling on the Execute.run
133    * 
134    * @return contents of the specs file
135    */
136   public static String[] getSpecs() {
137     if (specs == null) {
138       final File gccParent = CUtil.getExecutableLocation(GccCCompiler.CMD_PREFIX + "gcc.exe");
139       if (gccParent != null) {
140         //
141         // build a relative path like
142         // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs
143         //
144         //
145         // resolve it relative to the location of gcc.exe
146         //
147         final String relativePath = "../lib/gcc-lib/" + getMachine() +
148             '/' +
149             getVersion() +
150             "/specs";
151         final File specsFile = new File(gccParent, relativePath);
152         //
153         // found the specs file
154         //
155         try {
156           //
157           // read the lines in the file
158           //
159           final BufferedReader reader = new BufferedReader(new FileReader(specsFile));
160           final Vector<String> lines = new Vector<>(100);
161           String line = reader.readLine();
162           while (line != null) {
163             lines.addElement(line);
164             line = reader.readLine();
165           }
166           specs = new String[lines.size()];
167           lines.copyInto(specs);
168         } catch (final IOException ex) {
169         }
170       }
171     }
172     if (specs == null) {
173       specs = new String[0];
174     }
175     return specs;
176   }
177 
178   public static String getVersion() {
179     if (version == null) {
180       final String[] args = new String[] {
181           GccCCompiler.CMD_PREFIX + "gcc", "-dumpversion"
182       };
183       final String[] cmdout = CaptureStreamHandler.run(args);
184       if (cmdout.length == 0) {
185         version = "noversion";
186       } else {
187         version = cmdout[0];
188       }
189     }
190     return version;
191   }
192 
193   public static boolean isCaseSensitive() {
194     return true;
195   }
196 
197   /**
198    * Determines if task is running with cygwin
199    * 
200    * @return true if cygwin was detected
201    */
202   public static boolean isCygwin() {
203     return getMachine().indexOf("cygwin") > 0;
204   }
205 
206   private static boolean isHPUX() {
207     final String osname = System.getProperty("os.name").toLowerCase();
208     if (osname.contains("hp") && osname.contains("ux")) {
209       return true;
210     }
211     return false;
212   }
213 
214   /**
215    * 
216    * Parses the results of the specs file for a specific processor and
217    * options
218    * 
219    * @param specsContent
220    *          Contents of specs file as returned from getSpecs
221    * @param specSectionStart
222    *          start of spec section, for example "*cpp:"
223    * @param options
224    *          command line switches such as "-istart"
225    */
226   public static String[][]
227       parseSpecs(final String[] specsContent, final String specSectionStart, final String[] options) {
228     if (specsContent == null) {
229       throw new NullPointerException("specsContent");
230     }
231     if (specSectionStart == null) {
232       throw new NullPointerException("specSectionStart");
233     }
234     if (options == null) {
235       throw new NullPointerException("option");
236     }
237     final String[][] optionValues = new String[options.length][];
238     final StringBuffer optionValue = new StringBuffer(40);
239     for (int i = 0; i < specsContent.length; i++) {
240       String specLine = specsContent[i];
241       //
242       // if start of section then start paying attention
243       //
244       if (specLine.startsWith(specSectionStart)) {
245         final Vector<String>[] optionVectors = new Vector[options.length];
246         for (int j = 0; j < options.length; j++) {
247           optionVectors[j] = new Vector<>(10);
248         }
249         //
250         // go to next line and examine contents
251         // and repeat until end of file
252         //
253         for (i++; i < specsContent.length; i++) {
254           specLine = specsContent[i];
255           for (int j = 0; j < options.length; j++) {
256             int optionStart = specLine.indexOf(options[j]);
257             while (optionStart >= 0) {
258               optionValue.setLength(0);
259               //
260               // walk rest of line looking for first non
261               // whitespace
262               // and then next space
263               boolean hasNonBlank = false;
264               int k = optionStart + options[j].length();
265               for (; k < specLine.length(); k++) {
266                 //
267                 // either a blank or a "}" (close of
268                 // conditional)
269                 // section will end the path
270                 //
271                 if (specLine.charAt(k) == ' ' || specLine.charAt(k) == '}') {
272                   if (hasNonBlank) {
273                     break;
274                   }
275                 } else {
276                   hasNonBlank = true;
277                   optionValue.append(specLine.charAt(k));
278                 }
279               }
280               //
281               // transition back to whitespace
282               // value is over, add it to vector
283               if (hasNonBlank) {
284                 optionVectors[j].addElement(optionValue.toString());
285               }
286               //
287               // find next occurance on line
288               //
289               optionStart = specLine.indexOf(options[j], k);
290             }
291           }
292         }
293         //
294         // copy vectors over to option arrays
295         //
296         for (int j = 0; j < options.length; j++) {
297           optionValues[j] = new String[optionVectors[j].size()];
298           optionVectors[j].copyInto(optionValues[j]);
299         }
300       }
301     }
302     //
303     // fill in any missing option values with
304     // a zero-length string array
305     for (int i = 0; i < optionValues.length; i++) {
306       final String[] zeroLenArray = new String[0];
307       if (optionValues[i] == null) {
308         optionValues[i] = zeroLenArray;
309       }
310     }
311     return optionValues;
312   }
313 
314   private GccProcessor() {
315   }
316 }