from   quex.engine.misc.file_in import \
                                       open_file_or_die, \
                                       write_safely_and_close, \
                                       get_current_line_info_number, \
                                       error_msg
from   quex.engine.generator.code_fragment_base import CodeFragment
from   quex.blackboard import setup as Setup

UserCodeFragment_OpenLinePragma = {
#___________________________________________________________________________________
# Line pragmas allow to direct the 'virtual position' of a program in a file
# that was generated to its origin. That is, if an error occurs in line in a 
# C-program which is actually is the pasted code from a certain line in a .qx 
# file, then the compiler would print out the line number from the .qx file.
# 
# This mechanism relies on line pragmas of the form '#line xx "filename"' telling
# the compiler to count the lines from xx and consider them as being from filename.
#
# During code generation, the pasted code segments need to be followed by line
# pragmas resetting the original C-file as the origin, so that errors that occur
# in the 'real' code are not considered as coming from the .qx files.
# Therefore, the code generator introduces placeholders that are to be replaced
# once the whole code is generated.
#
#  ...[Language][0]   = the placeholder until the whole code is generated
#  ...[Language][1]   = template containing 'NUMBER' and 'FILENAME' that
#                       are to replaced in order to get the resetting line pragma.
#___________________________________________________________________________________
        "C": 
        [
            [ '/* POST-ADAPTION: FILL IN APPROPRIATE LINE PRAGMA */',
              '#   line NUMBER "FILENAME"' ],
            ['/* POST-ADAPTION: FILL IN APPROPRIATE LINE PRAGMA CppTemplate.txt */',
             '#   line NUMBER "CppTemplate.txt"' ]
        ],
   }

class UserCodeFragment(CodeFragment):
    def __init__(self, Code, Filename, LineN, LanguageDB=None):
        assert isinstance(Code, (str, unicode))
        assert isinstance(LanguageDB, dict) or LanguageDB is None
        assert isinstance(Filename, (str, unicode))
        assert isinstance(LineN, (int, long, float))

        self.filename = Filename
        self.line_n   = LineN

        CodeFragment.__init__(self, Code)

    def get_code(self):
        return self.adorn_with_source_reference(self.get_pure_code())

    def adorn_with_source_reference(self, Code, ReturnToSourceF=True):
        if len(Code.strip()) == 0: return ""

        # Even under Windows (tm), the '/' is accepted. Thus do not rely on 'normpath'
        norm_filename = Setup.get_file_reference(self.filename) 
        txt  = '\n#   line %i "%s"\n' % (self.line_n, norm_filename)
        txt += Code
        if ReturnToSourceF:
            if txt[-1] != "\n": txt = txt + "\n"
            txt += get_return_to_source_reference()
        return txt

def get_return_to_source_reference():
    return "\n" + UserCodeFragment_OpenLinePragma["C"][0][0] + "\n"

def UserCodeFragment_straighten_open_line_pragmas(filename, Language):
    if Language not in UserCodeFragment_OpenLinePragma.keys():
        return

    fh = open_file_or_die(filename)
    norm_filename = Setup.get_file_reference(filename)

    new_content = []
    line_n      = 0
    LinePragmaInfoList = UserCodeFragment_OpenLinePragma[Language]
    for line in fh.readlines():