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.os390;
21  
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.util.Vector;
26  
27  import org.apache.tools.ant.BuildException;
28  
29  import com.github.maven_nar.cpptasks.CCTask;
30  import com.github.maven_nar.cpptasks.CUtil;
31  import com.github.maven_nar.cpptasks.VersionInfo;
32  import com.github.maven_nar.cpptasks.compiler.CommandLineLinker;
33  import com.github.maven_nar.cpptasks.compiler.CommandLineLinkerConfiguration;
34  import com.github.maven_nar.cpptasks.compiler.LinkType;
35  import com.github.maven_nar.cpptasks.compiler.Linker;
36  import com.github.maven_nar.cpptasks.types.LibrarySet;
37  import com.github.maven_nar.cpptasks.types.LibraryTypeEnum;
38  
39  /**
40   * Adapter for the IBM (R) OS/390 (tm) Linker
41   *
42   * @author Hiram Chirino (cojonudo14@hotmail.com)
43   */
44  public final class OS390Linker extends CommandLineLinker {
45    private static final OS390Linker datasetLinker = new OS390Linker();
46    private static final OS390Linker dllLinker = new OS390Linker("", ".dll");
47    private static final OS390Linker instance = new OS390Linker("", "");
48  
49    private static int addLibraryPatterns(final String[] libnames, final StringBuffer buf, final String prefix,
50        final String extension, final String[] patterns, final int offset) {
51      for (int i = 0; i < libnames.length; i++) {
52        buf.setLength(0);
53        buf.append(prefix);
54        buf.append(libnames[i]);
55        buf.append(extension);
56        patterns[offset + i] = buf.toString();
57      }
58      return offset + libnames.length;
59    }
60  
61    public static OS390Linker getDataSetInstance() {
62      return datasetLinker;
63    }
64  
65    public static OS390Linker getInstance() {
66      return instance;
67    }
68  
69    private final boolean isADatasetLinker;
70    File outputFile;
71    private final String outputPrefix;
72    CCTask task;
73  
74    private OS390Linker() {
75      super("cxx", "/bogus", new String[] {
76          ".o", ".a", ".lib", ".xds"
77      }, new String[] {
78          ".dll", ".x"
79      }, ".xds", false, null);
80      this.outputPrefix = "";
81      this.isADatasetLinker = true;
82    }
83  
84    private OS390Linker(final String outputPrefix, final String outputSuffix) {
85      super("cxx", "/bogus", new String[] {
86          ".o", ".a", ".lib", ".x"
87      }, new String[] {
88        ".dll"
89      }, outputSuffix, false, null);
90      this.outputPrefix = outputPrefix;
91      this.isADatasetLinker = false;
92    }
93  
94    protected void addBase(final long base, final Vector<String> args) {
95    }
96  
97    protected void addEntry(final String entry, final Vector<String> args) {
98    }
99  
100   protected void addFixed(final Boolean fixed, final Vector<String> args) {
101   }
102 
103   protected void addImpliedArgs(final boolean debug, final LinkType linkType, final Vector<String> args) {
104     if (linkType.isSharedLibrary()) {
105       args.addElement("-W");
106       args.addElement("l,DLL");
107     }
108   }
109 
110   protected void addIncremental(final boolean incremental, final Vector<String> args) {
111   }
112 
113   @Override
114   protected String[] addLibrarySets(final CCTask task, final LibrarySet[] libsets, final Vector<String> preargs,
115       final Vector<String> midargs, final Vector<String> endargs) {
116     // If yo want to link against a library sitting in a dataset and
117     // not in the HFS, you can just use the //'dataset' notation
118     // to specify it. e.g:
119     // <libset dir="." libs="//'MQM.V5R2M0.SCSQLOAD'"/>
120     //
121     // We have to have special handling here because the file is not
122     // on the normal filesystem so the task will not noramly include it
123     // as part of the link command.
124     if (libsets != null) {
125       for (final LibrarySet libset : libsets) {
126         final String libs[] = libset.getLibs();
127         for (final String lib : libs) {
128           if (lib.startsWith("//")) {
129             endargs.addElement("-l");
130             endargs.addElement(lib);
131           } else if (libset.getDataset() != null) {
132             final String ds = libset.getDataset();
133             endargs.addElement("//'" + ds + "(" + lib + ")'");
134           }
135         }
136       }
137     }
138     return super.addLibrarySets(task, libsets, preargs, midargs, endargs);
139   }
140 
141   protected void addMap(final boolean map, final Vector<String> args) {
142   }
143 
144   protected void addStack(final int stack, final Vector<String> args) {
145   }
146 
147   @Override
148   public String getCommandFileSwitch(final String commandFile) {
149     return "@" + commandFile;
150   }
151 
152   @Override
153   public File[] getLibraryPath() {
154     return CUtil.getPathFromEnvironment("LIB", ";");
155   }
156 
157   @Override
158   public String[] getLibraryPatterns(final String[] libnames, final LibraryTypeEnum libType) {
159     final StringBuffer buf = new StringBuffer();
160     final String[] patterns = new String[libnames.length * 3];
161     int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0);
162     offset = addLibraryPatterns(libnames, buf, "", ".x", patterns, offset);
163     offset = addLibraryPatterns(libnames, buf, "", ".o", patterns, offset);
164     return patterns;
165   }
166 
167   @Override
168   public Linker getLinker(final LinkType linkType) {
169     if (this == datasetLinker) {
170       return datasetLinker;
171     }
172     if (linkType.isSharedLibrary()) {
173       return dllLinker;
174     }
175     return instance;
176   }
177 
178   @Override
179   public int getMaximumCommandLength() {
180     return Integer.MAX_VALUE;
181   }
182 
183   @Override
184   public String[] getOutputFileNames(final String baseName, final VersionInfo versionInfo) {
185     final String[] baseNames = super.getOutputFileNames(baseName, versionInfo);
186     if (this.outputPrefix.length() > 0) {
187       for (int i = 0; i < baseNames.length; i++) {
188         baseNames[i] = this.outputPrefix + baseNames[i];
189       }
190     }
191     return baseNames;
192   }
193 
194   @Override
195   protected String[] getOutputFileSwitch(final CCTask task, String outputFile) {
196     if (this.isADatasetLinker && task.getDataset() != null) {
197       final String ds = task.getDataset();
198       outputFile = "//'" + ds + "(" + outputFile + ")'";
199     }
200     return getOutputFileSwitch(outputFile);
201   }
202 
203   @Override
204   public String[] getOutputFileSwitch(final String outputFile) {
205     return new String[] {
206         "-o", outputFile
207     };
208   }
209 
210   @Override
211   public boolean isCaseSensitive() {
212     return OS390Processor.isCaseSensitive();
213   }
214 
215   @Override
216   public void link(final CCTask task, File outputFile, final String[] sourceFiles,
217       final CommandLineLinkerConfiguration config) throws BuildException {
218     this.task = task;
219     this.outputFile = outputFile;
220     if (this.isADatasetLinker) {
221       final int p = outputFile.getName().indexOf(".");
222       if (p >= 0) {
223         final String newname = outputFile.getName().substring(0, p);
224         outputFile = new File(outputFile.getParent(), newname);
225       }
226     }
227     super.link(task, outputFile, sourceFiles, config);
228   }
229 
230   @Override
231   protected int runCommand(final CCTask task, final File workingDir, final String[] cmdline) throws BuildException {
232     final int rc = super.runCommand(task, workingDir, cmdline);
233     // create the .xds file if everything was ok.
234     if (rc == 0) {
235       try {
236         this.outputFile.delete();
237         new FileOutputStream(this.outputFile).close();
238       } catch (final IOException e) {
239         throw new BuildException(e.getMessage());
240       }
241     }
242     return rc;
243   }
244 }