package nxm.xbc.lib;

import nxm.sys.lib.Midas;
import nxm.sys.lib.Shell;

/** Preprocesses a Fortran file. Currently this just uses a local copy of X-Midas's xfpp
    to accomplish this.

    @author  J. Czechowski IV
    @since   NeXtMidas 2.5.0
 */
public final class FortranPreprocessor {
  private static final boolean DEBUG = false; // Turns on debugging info in the C++ code.

  private boolean debug;   // Turns on debugging in the Java code
  private Midas   midas;   // The Midas context to use.

  static {
    if (!Shell.loadLibrary("xbc","lib","FortranPreprocessor")) {
      Shell.getSharedMidasContext().warning("Unable to load native library for FortranPreprocessor.");
    }
  }

  /** FortranPreprocessor Constructor
   *  @param midas The Midas Context
   *  @param debug The flag for enabling debugging
   */
  public FortranPreprocessor(Midas midas, boolean debug) {
    this.midas = midas;
    this.debug = debug;
  }

  /** Preprocesses a given Fortran file.
      @param inFile  The input file.
      @param outFile The output file.
      @param flags   The build flags used with the file (uses the C/C++ syntax, "-D_EEEI -D_NMFFT").
      @return true xfpp preprocessor return success, otherwise false
   */
  public boolean preprocess(String inFile, String outFile, String flags) {
    // xfpp options (flags)
    // i = Inline all of the include files (generates 'includes.list' file in current directory,
    //     which is then later processed by X-Midas's xpc utility)
    // s = Change PROGRAM statement to a subroutine call for for inclusion in a dynamic linked library.
    //     i.e. subroutine mh$<primitive_name>
    // h = Inserts the standalone header (subroutine MAINROUTINE) when used with the 's' option
    // ORIG 2.7.1 String xfppFlags = "is"+fixDefines(flags);
    String xfppFlags = "sh"+fixDefines(flags); // NTN: removed 'i' since we are NOT inlining the 'includes.list'

    if (debug) {
      midas.info("Calling xfpp "+inFile+" "+outFile+" "+xfppFlags);
    }
    return (xfpp(inFile, outFile, xfppFlags) == 0);
  }


  /** Converts the definitions in a C/C++ compile string to those used by xfpp. */
  private String fixDefines(String args) {
    String[] argList = args.split("[ ]+");
    StringBuffer defines = new StringBuffer();

    for (int i = 0; i < argList.length; i++) {
      if (argList[i].startsWith("-D")) {
        defines.append('#').append(argList[i].substring(2).trim());
      }
    }

    return defines.toString();
  }

  /** Calls the C++ version of xfpp. */
  private static native int xfpp(String inFile, String outFile, String flags);

}