/*
 *
 * Copyright 2002-2004 The Ant-Contrib project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package net.sf.antcontrib.cpptasks.openwatcom;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

import net.sf.antcontrib.cpptasks.CUtil;
import net.sf.antcontrib.cpptasks.TargetMatcher;
import net.sf.antcontrib.cpptasks.VersionInfo;
import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker;
import net.sf.antcontrib.cpptasks.compiler.LinkType;
import net.sf.antcontrib.cpptasks.platforms.WindowsPlatform;
import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum;

/**
 * Adapter for the OpenWatcom linker.
 *
 * @author Curt Arnold
 */
public abstract class OpenWatcomLinker
    extends CommandLineLinker {
  /**
   * Constructor.
   * @param command String command string (wcl386 or wfl386)
   * @param outputSuffix String output suffix
   */
  protected OpenWatcomLinker(final String command,
                             final String outputSuffix) {
    super(command, "-r", new String[] {".obj", ".lib", ".res"}
          ,
          new String[] {".map", ".pdb", ".lnk"}
          , outputSuffix, false, null);
  }

  /**
   * Add specified base address to linker options.
   * @param base long base address
   * @param args Vector command options
   */
  protected final void addBase(final long base, final Vector args) {
  }

  /**
   * Adds non-default entry point.
   * @param entry entry point name
   * @param args command line parameters
   */
  protected final void addEntry(final String entry, final Vector args) {
  }

  /**
   * Adds fixed option.
   * @param fixed if executable is fixed
   * @param args command line parameters
   */
  protected final void addFixed(final Boolean fixed, final Vector args) {
  }

   /**
   *  Adds other command line parameters.
   * @param debug boolean is debug
   * @param linkType LinkType link type
   * @param args Vector command line arguments
   */
  protected final void addImpliedArgs(final boolean debug,
                                final LinkType linkType,
                                final Vector args) {
    if (linkType.isExecutable()) {
      if (linkType.isSubsystemConsole()) {
        args.addElement("/bc");
      } else {
        if (linkType.isSubsystemGUI()) {
          args.addElement("/bg");
        }
      }
    }
    if (linkType.isSharedLibrary()) {
      args.addElement("/bd");
    }
  }

  /**
   * Add command line switch to force incremental linking.
   * @param incremental boolean do incremental linking
   * @param args Vector command line arguments
   */
  protected final void addIncremental(final boolean incremental,
                                      final Vector args) {
  }

  /**
   * Add command line switch to force map generation.
   * @param map boolean build map
   * @param args Vector command line arguments
   */
  protected final void addMap(final boolean map, final Vector args) {
    if (map) {
      args.addElement("/fm");
    }
  }

  /**
   * Add command line switch for stack reservation.
   * @param stack int stack size.
   * @param args Vector command line arguments.
   */
  protected final void addStack(final int stack, final Vector args) {
    if (stack >= 0) {
      String stackStr = Integer.toString(stack);
      args.addElement("/k" + stackStr);
    }
  }

  /**
   * Adds source or object files to the bidded fileset to
   * support version information.
   *
   * @param versionInfo version information
   * @param linkType link type
   * @param isDebug true if debug build
   * @param outputFile name of generated executable
   * @param objDir directory for generated files
   * @param matcher bidded fileset
   * @throws IOException if unable to write version resource
   */
  public final void addVersionFiles(final VersionInfo versionInfo,
                              final LinkType linkType,
                              final File outputFile,
                              final boolean isDebug,
                              final File objDir,
                              final TargetMatcher matcher) throws IOException {
    WindowsPlatform.addVersionFiles(versionInfo, linkType, outputFile, isDebug,
                                    objDir, matcher);
  }

  /**
   * Get command file switch.
   * @param commandFile String command file name
   * @return String command line option
   */
  public final String getCommandFileSwitch(final String commandFile) {
    return "@" + commandFile;
  }

  /**
   * Get search path for libraries.
   * @return File[] library path
   */
  public final File[] getLibraryPath() {
    return CUtil.getPathFromEnvironment("LIB", ";");
  }

  /**
   * Get file selectors for libraries.
   * @param libnames String[]
   * @param libType LibraryTypeEnum
   * @return String[]
   */
  public final String[] getLibraryPatterns(final String[] libnames,
                                           final LibraryTypeEnum libType) {
    return OpenWatcomProcessor.getLibraryPatterns(libnames, libType);
  }

  /**
   * Get maximum command line length.
   * @return int command line length
   */
  public final int getMaximumCommandLength() {
    return 1024;
  }

  /**
   * Get output file switch.
   * @param outFile Output file name
   * @return String[] command line switches
   */
  public final String[] getOutputFileSwitch(final String outFile) {
    return OpenWatcomProcessor.getOutputFileSwitch(outFile);
  }

  /**
   * Gets file name sensitivity of processors.
   * @return boolean true if case sensitive.
   */
  public final boolean isCaseSensitive() {
    return OpenWatcomProcessor.isCaseSensitive();
  }

}
