#!/usr/bin/env python

import re
import os
import sys

# -----------------
# Detect "Natural Docs" comments.
# -----------------
preserveText ="@preserve"
endSeparatorText ="------------------------------"
M_CODE = 0
M_COM1_BLOC = 1
M_COM2_BLOC = 2
reStarTextComBloc =     re.compile(r"^ *\/\*+ *(?! )")
reStarCom2Bloc =        re.compile(r"^ *\/\*\*")
reStarCom1Bloc =        re.compile(r"^ *\/\*")
reEndComBloc =          re.compile(r"\*\/")
reEndSepComBloc =       re.compile(r"\-{30} *\*\/")
reEndLine =             re.compile(r"\n")
reProblematicEndLine =  re.compile(r"\\\n")

def preserveCom (inputFilename, outputFilename):
    print "Preserving comments to: ", outputFilename, " ",

    if not os.path.isfile(inputFilename):
        print "\nProcess aborted due to errors."
        sys.exit('ERROR: Input file "%s" does not exist!' % inputFilename)

    dirOut = os.path.dirname(outputFilename)
    if dirOut == "":
        print "\nProcess aborted due to errors."
        sys.exit('ERROR: Output file "%s" without path!' % outputFilename)

    if not os.path.exists(dirOut):
        os.makedirs(dirOut)
    fOut = open(outputFilename,"w")
    fIn = open(inputFilename)

    mode = M_CODE
    previousProblematicEndLine = False
    lineNumber = 0
    for line in fIn:
        lineNumber += 1
        startCom = -1
        endCom = -1
        if mode == M_CODE and not previousProblematicEndLine:
            oo = reStarCom2Bloc.search(line)
            if oo: 
                startCom = oo.end()
                mode = M_COM2_BLOC
            else:
                oo = reStarCom1Bloc.search(line)
                if oo: 
                    startCom = oo.end()
                    mode = M_COM1_BLOC

        if mode != M_CODE:
            modeOld = mode
            previousProblematicEndLine = False
            oo = reEndComBloc.search(line)
            if oo: 
                endCom = oo.start()
                mode = M_CODE

            if endCom == -1:
                endCom = reEndLine.search(line).start()

            if startCom >= 0 and startCom <= endCom: # first line 
                aux = preserveText
                if modeOld == M_COM1_BLOC: # Set simple comment block to comment-2 block
                    aux = "*" + preserveText
                startText = reStarTextComBloc.search(line).end()
                if line[startText:startText+1] != "\n": # Add line if start block with text
                    aux += "\n"
                line = line[:startCom] + aux + line[startCom:]
            if mode == M_CODE: # last line
                if not reEndSepComBloc.search(line): # add separator at last line of block if not found
                    endCom = reEndComBloc.search(line).start()
                    line = ( line[:endCom] + 
                                 endSeparatorText + 
                                 line[endCom:] )

        fOut.write(line)
        if mode == M_CODE: 
            if reProblematicEndLine.search(line):
                previousProblematicEndLine = True
            else:
                previousProblematicEndLine = False

    print "Done!"
    fIn.close()
    fOut.close()
    return outputFilename
    
# -----------------
# main
# -----------------
if __name__ == '__main__':
    preserveCom(sys.argv[1],sys.argv[2])
