diff Compilable.py @ 0:28b636105ed6

Working version of codeOptimizer. -Still needs to implement more finegrained control per file basis. -CXXFLAGS are hardcoded.
author Tom Fredrik Blenning Klaussen <bfg@blenning.no>
date Sat, 15 Sep 2012 20:34:39 +0200
parents
children a1224150b8f6
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Compilable.py	Sat Sep 15 20:34:39 2012 +0200
@@ -0,0 +1,133 @@
+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):
+        self.loadFile()
+        str = ''
+        for i in range(len(self.lines)):
+            if not i in self.replace:
+                str += self.lines[i]
+            else:
+                str += self.replace[i]
+        return str
+
+    def works(self):
+        return tryCompileBuffer(self.activeBuffer(), 'g++', self.flags)
+
+    def deactivateLine(self, i):
+        self.replace[i] = "\n"
+
+    def activateLine(self, i):
+        del self.replace[i]
+
+    def loadFile(self):
+        if self.lines == None:
+            f = open(self.path, 'r')
+            self.lines = f.readlines()
+            f.close()
+            self.replace = {}
+
+    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 = []
+        for n in l:
+            self.deactivateLine(n)
+            print 'Trying to compile ' + self.path + ' without ' + self.getPathname(self.lines[n])
+            if self.works():
+                retVal.append(n)
+            else:
+                self.activateLine(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):
+        l = self.includeLines()
+        retVal = []
+        for n in l:
+            if n not in self.replace:
+                rstring = 'class ' + self.getClassname(self.lines[n]) + ';\n'
+                self.replace[n] = rstring
+                if self.works():
+                    retVal.append(n)
+                else:
+                    self.activateLine(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