#!/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 -- 2007-06-03"
__copyright__ = "Copyright (C) 2004-2007 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 2007

# Python modules
import sys
import getopt
import os.path

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

# FFC modules
from ffc.common.debug import *
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:O", \
        ["help", "version", "debug=", "silent", "language=", "representation=", "optimize"])
    except getopt.GetoptError:
        usage()
        return 2

    # Check that we got a filename
    if opts == [("-v", "")] or opts == [("--version", "")]:
        version()
        sys.exit(0)
    elif not args:
        usage()
        return 2

    # Set default arguments
    representation = FFC_REPRESENTATION
    language = FFC_LANGUAGE
    debuglevel = FFC_DEBUG_LEVEL
    options = FFC_OPTIONS

    # Get options
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            return 0
        elif opt in ("-v", "--version"):
            version()
            return 0
        elif opt in  ("-d", "--debug"):
            debuglevel = int(arg)
        elif opt in ("-s", "--silent"):
            debuglevel = -1
        elif opt in  ("-l", "--language"):
            language = arg
        elif opt in  ("-r", "--representation"):
            if arg in (FFC_REPRESENTATION, "quadrature"):
                representation = arg
            else:
                usage()
                return 2
        elif opt in  ("-f"):
            if "=" in arg and arg.split("=")[0] + "=" in options:
                options[arg.split("=")[0] + "="] = arg.split("=")[1]
            elif arg in options:
                options[arg] = True
            elif arg[:3] == "no-":
                options[arg] = True
            else:
                usage()
                return 2
        elif opt in ("-O", "--optimize"):
            options["optimize"] = True

    # Set debug level
    setlevel(debuglevel)

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

    # Silly warning
    if not os.path.join("foo", "bar") == "foo/bar":
        debug("*** Warning: Please consider using another operating system ;-)")

    # call parser and compiler for each file
    for filename in args:
        # parse current file
        outname = __make_module(filename, representation, language, options)
        # compile generated file (also provide a namespace)
        ns = {}
        # catch exceptions only if debug level is non-negative
        if debuglevel >= 1:
            execfile(outname, ns)
        else:
            try:
                execfile(outname, ns)
            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 usage():
    "Display usage info."
    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 version():
    "Display 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

def __make_module(filename, representation, language, 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 = filename.replace(".form", "")
    outname = prefix + ".py"
    debug("Preprocessing form file: %s --> %s\n" % (filename, outname))

    # 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\", \"%s\", %s)
""" % (input, prefix, representation, language, options)

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

    # Return output file name
    return outname

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