#!/usr/bin/env python
#
# This script is the command-line interface to FFC. It parses
# command-line arguments and wraps the given form file code in a
# Python module which is then executed.

__author__ = "Anders Logg (logg@simula.no)"
__date__ = "2004-10-14 -- 2008-09-27"
__copyright__ = "Copyright (C) 2004-2008 Anders Logg"
__license__  = "GNU GPL version 3 or any later version"

# Modified by Johan Jansson, 2005
# Modified by Ola Skavhaug, 2006
# Modified by Kristian B. Oelgaard 2008
# Modified by Dag Lindbo, 2008

# Python modules
import sys
import getopt
import os.path

# Enable ffc from within demo and sandbox without installation
sys.path.append("../")

# FFC modules
from ffc.common.debug import warning, error, debug, setlevel
from ffc.common.constants import *
from ffc.common.exceptions import *

def main(argv):
    "Main function"

    # Get command-line arguments
    try:
        opts, args = getopt.getopt(argv, "hvd:sl:r:f:Oo:", \
        ["help", "version", "debug=", "silent", "language=", "representation=", "optimize", "output-directory="])
    except getopt.GetoptError:
        error("Illegal command-line arguments")
        print_usage()
        return 2

    # Check for -h
    if len(argv) == 1 and argv[0] in ("-h", "--help"):
        print_usage()
        return 0

    # Check for -v
    if len(argv) == 1 and argv[0] in ("-v", "--version"):
        print_version()
        return 0

    # Check that we get at least one file
    if len(args) == 0:
        error("Missing file")
        return 2
    
    # Set default arguments
    debuglevel = FFC_DEBUG_LEVEL
    options = FFC_OPTIONS.copy()

    # Parse command-line options
    for opt, arg in opts:
        if opt in  ("-d", "--debug"):
            debuglevel = int(arg)
        elif opt in ("-s", "--silent"):
            debuglevel = -1
        elif opt in  ("-l", "--language"):
            options["language"] = arg
        elif opt in  ("-r", "--representation"):
            options["representation"] = arg
        elif opt in  ("-f"):
            if len(arg.split("=")) == 2:
                (key, value) = arg.split("=")
                options[key] = value
            elif len(arg.split("==")) == 1:
                key = arg.split("=")[0]
                options[arg] = True
            else:
                print_usage()
                return 2
        elif opt in ("-O", "--optimize"):
            options["optimize"] = True
        elif opt in ("-o", "--output-directory"):
            options["output_dir"] = arg

    # Set debug level
    setlevel(debuglevel)

    # Print a nice message
    if debuglevel > -1:
        print_version()

    # Call parser and compiler for each file
    for filename in args:

        # Get filename suffix
        suffix = filename.split(".")[-1]

        # Check file suffix and parse file/generate module
        if suffix == "ufl":
            script = _make_script_ufl(filename, options)
        elif suffix == "form":
            script = _make_script_form(filename, options)

        # Catch exceptions only if debug level is non-negative
        if debuglevel >= 1:
            execfile(script, {})
        else:
            try:
                execfile(script, {})
            except FormError, exception:
                print ""
                print "*** Error at " + str(exception.expression)
                print "*** " + exception.message
                print "*** To get more information about this error, rerun ffc with the option -d1."
                return 2
            except RuntimeError, exception:
                print "*** " + str(exception)
                print "*** To get more information about this error, rerun ffc with the option -d1."
                return 2
            except Exception, exception:
                print "*** " + str(exception)
                print "*** To get more information about this error, rerun ffc with the option -d1."
                return 2

    return 0

def print_usage():
    "Print usage info"
    print_version()
    print """Usage: ffc [OPTION]... input.form

For information about the FFC command-line interface, refer to
the FFC man page which may invoked by 'man ffc' (if installed).
"""
    return

def print_version():
    "Print version number"
    print("This is FFC, the FEniCS Form Compiler, version %s." % FFC_VERSION)
    print("For further information, go to http://www.fenics.org/ffc/.\n")
    return

# New version for .ufl files
def _make_script_ufl(filename, options):
    "Create Python script from given .ufl file and return name of script"

    # Get prefix of file name and generate Python script file name
    prefix = ".".join(filename.split(".")[:-1])
    script = prefix + ".py"
    debug("Preprocessing form file: %s --> %s\n" % (filename, script))

    # Read input
    infile = open(filename, "r")
    input = infile.read()
    infile.close()

    # Generate output
    output = """\
from ufl import *
from ffc import compile_ufl

# Reserved variables for forms
(a, L, M) = (None, None, None)

# Reserved variable for element
element = None

%s
compile_ufl([a, L, M, element], \"%s\", %s)
""" % (input, prefix, options)

    # Write output
    outfile = open(script, "w")
    outfile.write(output)
    outfile.close()

    # Return script filename
    return script

# Old version for .form files
def _make_script_form(filename, options):
    "Create Python module from given .form file and return name of module file"

    # Get prefix of file name and generate Python script file name
    prefix = ".".join(filename.split(".")[:-1])
    script = prefix + ".py"
    debug("Preprocessing form file: %s --> %s\n" % (filename, script))

    # Read input
    infile = open(filename, "r")
    input = infile.read()
    infile.close()

    # Generate output
    output = """\
from ffc import *

# Reserved variables for forms
(a, L, M) = (None, None, None)

# Reserved variable for element
element = None

%s
compile([a, L, M, element], \"%s\", %s)
""" % (input, prefix, options)

    # Write output
    outfile = open(script, "w")
    outfile.write(output)
    outfile.close()

    # Return script filename
    return script

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
