summaryrefslogtreecommitdiff
path: root/solenv/bin/pchdelta.py
diff options
context:
space:
mode:
Diffstat (limited to 'solenv/bin/pchdelta.py')
-rwxr-xr-xsolenv/bin/pchdelta.py149
1 files changed, 149 insertions, 0 deletions
diff --git a/solenv/bin/pchdelta.py b/solenv/bin/pchdelta.py
new file mode 100755
index 000000000000..52a0df4ecc5d
--- /dev/null
+++ b/solenv/bin/pchdelta.py
@@ -0,0 +1,149 @@
+#!/usr/bin/python
+
+# ------------------------------------------------------------------------------
+# Hacky little delta debug tool to figure out the proper includes for a pch file
+#
+# Usage:
+#
+# pchdelta.py <pch_target> <dir1> [<dir2> <dir3> ...]
+#
+# <pch_target> File to perform delta debugging on. The section to test
+# is delimeted by '//---MARKER---' lines.
+# <dir1> .. <dirn> Sequence of directories to run dmake in to test if the
+# modification works
+#
+# Examples:
+#
+# pchdelta.py inc/pch/precompiled_sfx2.hxx inc source/dialog
+#
+# Run pchdelta inside sfx2 first building the pch files and then files in
+# source/dialog
+#
+# ------------------------------------------------------------------------------
+
+import os
+import os.path
+import sys
+
+# C++
+MARKER="//---MARKER---\n"
+
+# dmake
+#MARKER="#---MARKER---\n"
+
+# ------------------------------------------------------------------------------
+# Sequentially build all argument directories from scratch
+
+def testSequenceBuild(dirlist):
+ cwd = os.path.abspath(os.getcwd())
+ for path in dirlist:
+ os.chdir(path)
+ buildcommand = "dmake -u"
+ buildcommand += " >>" + cwd + "/buildlog.txt 2>&1"
+ buildresult = os.system(buildcommand)
+ os.chdir(cwd)
+ if buildresult != 0:
+ return False
+ return True
+
+# ------------------------------------------------------------------------------
+# Dump out the delta file with corresponding markers
+
+def writePch(pchname, header, footer, acceptedlines, testlines):
+ outputfile = file(pchname, "w")
+ outputfile.write(header)
+ outputfile.write(MARKER)
+ outputfile.write("\n".join(acceptedlines))
+ if len(testlines) > 0:
+ outputfile.write("\n\n//---Candidate marker---\n")
+ outputfile.write("\n".join(testlines) + "\n")
+ outputfile.write("//---Candidate marker end---\n")
+ outputfile.write(MARKER)
+ outputfile.write(footer)
+ outputfile.close()
+
+
+# ------------------------------------------------------------------------------
+# Recursive tester routine. Test the segment given and if an error is
+# encountered splits the segment into <fanout> subsegment and recurses. Failing
+# one liners are rejected. The set of accepted lines are built sequentially from
+# the beginning.
+
+def binaryTest(dirlist, lines, pchname, header, footer, acceptedlines, indent, startpoint):
+ linecount = len(lines)
+ if linecount == 0:
+ return
+ # Test if this slice passes the buildtest
+ writePch(pchname, header, footer, acceptedlines, lines)
+ if testSequenceBuild(dirlist):
+ return acceptedlines + lines
+
+ # Reject one liners
+ if linecount == 1:
+ print indent + "Rejected: " + lines[0]
+ return acceptedlines
+
+ # Recurse with multiline slices
+ fanout = 4
+ splits = []
+ for i in range(3):
+ splits.append(linecount * (i + 1) / fanout)
+ splits.append(linecount)
+
+ splitstart = 0
+ for splitend in splits:
+ # avoid splitting in case we have no resulting lines
+ if (splitend - splitstart) == 0:
+ continue
+ splitslice = lines[splitstart:splitend]
+ print indent + "[" + str(startpoint + splitstart) + ":" + str(startpoint + splitend) + "] (" + str(splitend - splitstart) + ")"
+ acceptedlines = binaryTest(dirlist, splitslice, pchname, header, footer, acceptedlines, indent + " ", startpoint + splitstart)
+ splitstart = splitend
+
+ return acceptedlines
+
+# ------------------------------------------------------------------------------
+# Main entry point
+
+if len(sys.argv) < 3:
+ print "Usage: " + sys.argv[0] + " <pch_target> <dir1> [<dir2> <dir3> ...]"
+ sys.exit(1)
+
+pchname = os.path.abspath(sys.argv[1])
+dirlist = sys.argv[2:]
+
+# remove old build log file
+if os.path.exists("buildlog.txt"):
+ os.remove("buildlog.txt")
+
+# test for corner case of everything working from the start
+if testSequenceBuild(dirlist):
+ print "pch working, nothing to do."
+ sys.exit(0)
+
+# Open the header file for reading
+inputfile = file(pchname, "r+")
+inputdata = inputfile.read()
+inputfile.close()
+
+segments = inputdata.split(MARKER)
+header = segments[0]
+footer = segments[2]
+lines = segments[1].split("\n")
+
+writePch(pchname + "_backup", header, footer, lines, [])
+
+# test for corner case of no convergence possible
+writePch(pchname, header, footer, [], [])
+if not testSequenceBuild(dirlist):
+ writePch(pchname, header, footer, lines, [])
+ print "Building with no candidate lines failed. Convergence questionable, aborting."
+ sys.exit(0)
+
+# Starting pruning
+print "Starting evaluation of " + str(len(lines)) + " lines"
+acceptedlines = binaryTest(dirlist, lines, pchname, header, footer, [], "", 0)
+writePch(pchname, header, footer, acceptedlines, [])
+
+
+