// $Id: stf77.java,v 1.1 2001/02/23 04:10:58 m-hirano Exp $
// $RWC_Release: Omni-1.6 $
// $RWC_Copyright:
//  Omni Compiler Software Version 1.5-1.6
//  Copyright (C) 2002 PC Cluster Consortium
//  
//  This software is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License version
//  2.1 published by the Free Software Foundation.
//  
//  Omni Compiler Software Version 1.0-1.4
//  Copyright (C) 1999, 2000, 2001.
//   Tsukuba Research Center, Real World Computing Partnership, Japan.
//  
//  Please check the Copyright and License information in the files named
//  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
//  Software release kit.
//  
//  
//  $
//
// Fortran driver for test
//
package st;
import exc.object.*;
import exc.openmp.*;

public class stf77 extends exc.util.ccDriver {

  protected boolean omp_flag = true; 
  protected boolean checkNaN = false;
  protected boolean coredumpNaN = false;
  protected boolean pedanticEquiv = false;
  protected boolean pedanticData = false;
  protected boolean pedanticCommon = false;
  protected boolean doubleAlign = false;
  protected boolean disableQCZFolding = false;
  protected boolean disableQOpt = false;
  protected boolean implicitUndef = false;
  protected boolean checkArrayRange = false;
  protected String varSizeOpts = "";

  protected boolean checkVarSizeArgs(String aArg, int start) {
      String nStr = aArg.substring(start);
      if (nStr.equals("")) {
	  backend_opts += " " + aArg;
	  return false;
      } else {
	  boolean nonNum = false;
	  int len = nStr.length();
	  for (int i = 0; i < len; i++) {
	      switch (nStr.charAt(i)) {
		  case '0': case '1': case '2': case '3': case '4':
		  case '5': case '6': case '7': case '8': case '9': {
		      break;
		  }
		  default: {
		      nonNum = true;
		      break;
		  }
	      }
	      if (nonNum) {
		  break;
	      }
	  }
	  if (nonNum) {
	      backend_opts += " " + aArg;
	      return false;
	  } else {
	      varSizeOpts += " " + aArg;
	      return true;
	  }
      }

      //      boolean ret = true;
      //      try {
      //	  int sz = Integer.parseInt(aArg.substring(start), 10);
      //      }
      //      catch (NumberFormatException e) {
      //	  ret = false;
      //      }
      //      finally {
      //	  if (ret == true) {
      //	      varSizeOpts += " " + aArg;
      //	  } else {
      //	      backend_opts += " " + aArg;
      //	  }
      //      }
      //      return ret;
  }

  public stf77(){ super("stf77"); }
  public stf77(String name){ super(name); }

  protected String backend_opts = "";

  public static void main(String args[]){ 
    stf77 driver = new stf77();
    driver.run(args);
  }

  public boolean parseArg(String arg){ 
    if(arg.equals("-omp")){
      omp_flag = false;
      return true;
    } else if (arg.equals("-checkNaN")) {
	checkNaN = true;
	return true;
    } else if (arg.equals("-coredumpNaN")) {
	checkNaN = true;
	coredumpNaN = true;
	return true;
    } else if (arg.equals("-pedanticEquivalence")) {
	pedanticEquiv = true;
	return true;
    } else if (arg.equals("-pedanticDataType")) {
	pedanticData = true;
	return true;
    } else if (arg.equals("-pedanticCommon")) {
	pedanticCommon = true;
	return true;
    } else if (arg.equals("-pedanticAll")) {
	pedanticEquiv = true;
	pedanticData = true;
	pedanticCommon = true;
	return true;
    } else if (arg.equals("-doubleAlign")) {
	doubleAlign = true;
	return true;
    } else if (arg.equals("--gcc-huge-common")) {
        XobjectFile.gcc_huge_common_bug = true;
	return true;
    } else if (arg.equals("-disableQCZFolding")) {
	disableQCZFolding = true;
	return true;
    } else if (arg.equals("-disableQOpt")) {
	disableQOpt = true;
	return true;
    } else if (arg.equals("-u")) {
	implicitUndef = true;
	return true;
    } else if (arg.equals("-C")) {
	checkArrayRange = true;
	return true;
    } else if (arg.charAt(0) == '-' &&
	       (arg.charAt(1) == 'i' ||
		arg.charAt(1) == 'r' ||
		arg.charAt(1) == 'd' ||
		arg.charAt(1) == 'm')) {
	if (arg.charAt(2) != 'd') {
	    return checkVarSizeArgs(arg, 2);
	} else {
	    return checkVarSizeArgs(arg, 3);
	}
    } else {
	backend_opts += " " + arg;
	return false;
    }
  }

  public void printUsage() { 
    System.err.println("options: -omp, ignore OpenMP directives");
    System.err.println("options: -C, check range of array access (not implemented, only for compatibility)");
    System.err.println("options: -u, treat variables used/defined implicitly as undefined");
    System.err.println("options: -i#, set default integer size to # bytes");
    System.err.println("options: -r#, set default single precision real size to # bytes");
    System.err.println("options: -d#, set default double precision real size to # bytes");
    System.err.println("options: -m#, set precision of quad/multiple precision real to # bits (if configured)");
    System.err.println("options: -md#, set precision of quad/multiple precision real to # decimal digits (if configured)");
    System.err.println("options: -doubleAlign, if alignment of double is NOT sizeof double, treat alignment of double is sizeof double");
    System.err.println("options: -disableQCZFolding, disable complex and quad/multiple precision real (if configured) constant folding for (slight) precision improvement");
    System.err.println("options: -disableQOpt, disable quad/multiple precision real specific optimizations (if configured)");
    System.err.println("options: -pedanticEquivalence, not allow to be equivalent character variables to other types by EQUIVALENCE statement");
    System.err.println("options: -pedanticDataType, not allow to initialize non-character variables with characters by DATA statement");
    System.err.println("options: -pedanticCommon, not allow non-standard initialization in common block");
    System.err.println("options: -pedanticAll, imply all other -pedantic* options");
    System.err.println("options: -checkNaN, generate floating point exception checking code");
    System.err.println("options: -coredumpNaN, generate floating point exception checking code and dumping core when the exception occur");
  }

  public void init(){
    cc_opts += " "+getTemplateValue("OMPC_CFLAGS");
    if(omp_flag){
      cpp_opts += " -DOMPC -D_OPENMP ";
      ld_opts +=  " "+getTemplateValue("OMPC_F_OMP_MAIN");
      ld_opts +=  " "+getTemplateValue("OMPC_F_OMP_LDFLAGS");
    } else {
      ld_opts +=  " "+getTemplateValue("OMPC_F_MAIN");
      ld_opts +=  " "+getTemplateValue("OMPC_F_LDFLAGS");
      ffront_opts += "-omp";
    }
    if (backend_opts != "") {
	cc_opts += " " + backend_opts;
    }
    if (checkNaN) {
	ffront_opts += " -checkNaN ";
    }
    if (coredumpNaN) {
	ffront_opts += " -coredumpNaN ";
    }
    if (pedanticEquiv) {
	ffront_opts += " -pedanticEquivalence ";
    }
    if (pedanticData) {
	ffront_opts += " -pedanticDataType ";
    }
    if (pedanticCommon) {
	ffront_opts += " -pedanticCommon ";
    }
    if (doubleAlign) {
	ffront_opts += " -doubleAlign ";
    }
    if (disableQCZFolding) {
	ffront_opts += " -disableQCZFolding ";
    }
    if (disableQOpt) {
	ffront_opts += " -disableQOpt ";
    }
    if (implicitUndef) {
	ffront_opts += " -u ";
    }
    if (checkArrayRange) {
	ffront_opts += " -C ";
    }
    ffront_opts += " " + varSizeOpts;
  }

  public void run(XobjectFile f){
    if(!omp_flag) return;	// no OpenMP
    if(verbose) System.err.println("OpenMP pass ...");
    OMPtranslate op = new OMPtranslate();
    op.init(f);
    f.iterateDef(op);	// transform OMP pragma 
    if(OMP.errorFlags){
      System.err.println("error in OpenMP. stop.");
      System.exit(1);
    }
  }
}


