view Compilable.py @ 14:d98bd27f77b2 default tip

Testcase for loops.
author Tom Fredrik Blenning Klaussen <bfg@blenning.no>
date Wed, 14 Nov 2012 22:18:24 +0100
parents 09b39021c4af
children
line wrap: on
line source

import subprocess, re

def tryCompileFile(file, compiler, flags):
    cmd = compiler + " -x c++ -o /dev/null " + flags + " -c " + file
    devnull = open('/dev/null', 'w')
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                         stdout=devnull, stderr=None, shell=True)
    s = p.wait()
    devnull.close()
    return s == 0

def tryCompileBuffer(buffer, compiler, flags):
    cmd = compiler + " -x c++ -o /dev/null " + flags + " -c -"
    devnull = open('/dev/null', 'w')
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                         stdout=devnull, stderr=devnull, shell=True)
    p.stdin.write(buffer)
    p.stdin.close()
    s = p.wait()
    devnull.close()
    return s == 0



class Compilable:
    def __init__(self, path):
        self.path = path
        self.flags = ''
        self.lines = None

    def setFlags(self, flags):
        self.flags = flags

    def worksWithoutModifications(self):
        return tryCompileFile(self.path, 'g++', self.flags)

    def activeBuffer(self, replace):
        self.loadFile()
        str = ''
        for i in range(len(self.lines)):
            if not i in replace:
                str += self.lines[i]
            else:
                str += replace[i]
        return str

    def works(self, replace):
        return tryCompileBuffer(self.activeBuffer(replace), 'g++', self.flags)

    def loadFile(self):
        if self.lines == None:
            f = open(self.path, 'r')
            self.lines = f.readlines()
            f.close()

    def includeLines(self):
        self.loadFile()
        pattern = '^\s*#include '
        prog = re.compile(pattern)
        res = []
        for i in range(len(self.lines)):
            if prog.match(self.lines[i].rstrip()):
                res.append(i)
        return res

    def removeRemovableIncludes(self):
        l = self.includeLines()
        retVal = []
        replace = {}
        for n in l:
            replace[n] = '\n'
            print 'Trying to compile ' + self.path + ' without ' + self.getPathname(self.lines[n])
            if self.works(replace):
                retVal.append(n)
            else:
                del replace[n]

        return retVal

    @staticmethod
    def getPathname(str):
        pattern = '^\s*#include ["<]([^">]+)[">]'
        prog = re.compile(pattern)
        m = prog.search(str)
        include = m.group(1)
        return include


    @staticmethod
    def getClassname(str):
        include = Compilable.getPathname(str)

        pattern = '[^/]+$'
        prog = re.compile(pattern)
        m = prog.search(include)
        filename = m.group(0)

        pattern = '^[^.]+'
        prog = re.compile(pattern)
        m = prog.search(filename)
        basename = m.group(0)

        return basename

    def replaceIncludes(self, replace):
        l = self.includeLines()
        retVal = []
        for n in l:
            if n not in replace:
                rstring = 'class ' + self.getClassname(self.lines[n]) + ';\n'
                replace[n] = rstring
                if self.works(replace):
                    retVal.append(n)
                else:
                    del replace[n]
        return retVal

    def dependencies(self):
        lines = self.includeLines()
        retVal = []
        for line in lines:
            retVal.append(self.getPathname(self.lines[line]))
        return retVal


    def __repr__(self):
        return self.path


    @staticmethod
    def acceptsFile(name):
        if name.endswith(".hpp"):
            return True
        if name.endswith(".h"):
            return True
        if name.endswith(".cpp"):
            return True
        return False