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