#!/usr/bin/python
#-----------------------------------------------------------------------
# critTer2 script
#-----------------------------------------------------------------------

import sys
import os
from subprocess import call
from shutil import rmtree

#-----------------------------------------------------------------------

CRITTER_DIR = os.path.dirname(__file__)[0:-len('/bin')]
CRITTER_CLS_DIR = CRITTER_DIR + '/build/classes/main'
CRITTER_JAR_DIR = CRITTER_DIR + '/Jars'
TEMP_DIR = './critTer_bak'
CPATH = \
    CRITTER_JAR_DIR + '/cetus.jar' + ':' + \
    CRITTER_JAR_DIR + '/antlr-3.5.1-complete.jar' + ':' + \
    CRITTER_CLS_DIR

#-----------------------------------------------------------------------
#-----------------------------------------------------------------------

# Return line, making sure that it ends with a newline character.

def fullLine(line):
    if line.endswith('\n'):
        return line
    return line + '\n'

#-----------------------------------------------------------------------

# Splice pragmas into file frompath which indicate line numbers, and
# which delimit includes of standard .h files.  Store the result in
# file topath.

def annotate(frompath, topath):
    num = 1
    with open(frompath, 'r') as student_code:
        with open(topath, 'w') as modded:
            modded.write('typedef int* __WAIT_STATUS;\n')
            for line in student_code:
                modded.write('#pragma critTer:' + str(num) + ':' + str(frompath) + ':\n')
                if (line.lstrip().startswith('#include')) \
                        and ('<' in line) and ('>' in line):
                    modded.write('#pragma critTer:startStdInclude:\n')
                    modded.write(fullLine(line))
                    modded.write('#pragma critTer:endStdInclude:\n')
                elif (line.lstrip().startswith('#include')) \
                        and ('\"' in line):
                    modded.write('#pragma critTer:startStudentInclude:\n')
                    modded.write(fullLine(line))
                    modded.write('#pragma critTer:endStudentInclude:\n')
                else:
                    modded.write(fullLine(line))
                num += 1

#-----------------------------------------------------------------------

def main():

	# Validate command-line arguments
    if len(sys.argv) == 1:
        print >> sys.stderr, "No arguments given!"
        sys.exit(1)
    for arg in sys.argv[1:]:
        if not os.path.exists(arg):
            print >> sys.stderr, arg + ' does not exist.'
            sys.exit(1)

    # Start the string of command-line arguments to be passed to cetus.
    argsPrefix = '-preprocessor="gcc217 -E -C -dD" -path="' + \
        os.getcwd() + '/" '

    # If TEMP_DIR doesn't exist, then create it.
    if not os.path.exists(TEMP_DIR):
        os.makedirs(TEMP_DIR)

	# Populate TEMP_DIR with line-numbered versions of each .c file
    # specified as a command-line argument.
    for arg in sys.argv[1:]:
        if arg.endswith('.c'):
            cFile = arg
            annotatedCFile = TEMP_DIR + '/' + arg
            annotate(cFile, annotatedCFile)
            # args += annotatedCFile + " "

    # Populate TEMP_DIR with annotated versions of each .h file in
    # the working directory.
    for hFile in os.listdir('.'):
        if hFile.endswith('.h'):
            annotatedHFile = TEMP_DIR + '/' + hFile
            annotate(hFile, annotatedHFile)
            
    # Execute Cetus to (1) parse the line-numbered .c files that are
    # in TEMP_DIR (placing the resulting files in the ./cetus_output
    # directory), and (2) write its critique to stdout.
    for arg in sys.argv[1:]:
        args = argsPrefix + TEMP_DIR + '/' + arg
        print >> sys.stderr
        print >> sys.stderr, 'Checking ' + arg
        call('java -cp "' + CPATH + '" critter2.Critter ' + args,
            shell=True)
	
	# Delete the temporary directories.
    rmtree('./critTer_bak')

#-----------------------------------------------------------------------

if __name__ == "__main__":
    main()
