xref: /aoo42x/main/solenv/bin/pchdelta.py (revision cdf0e10c)
1*cdf0e10cSrcweir#!/usr/bin/python
2*cdf0e10cSrcweir
3*cdf0e10cSrcweir# ------------------------------------------------------------------------------
4*cdf0e10cSrcweir# Hacky little delta debug tool to figure out the proper includes for a pch file
5*cdf0e10cSrcweir#
6*cdf0e10cSrcweir# Usage:
7*cdf0e10cSrcweir#
8*cdf0e10cSrcweir# pchdelta.py <pch_target> <dir1> [<dir2> <dir3> ...]
9*cdf0e10cSrcweir#
10*cdf0e10cSrcweir# <pch_target>      File to perform delta debugging on. The section to test
11*cdf0e10cSrcweir#                   is delimeted by '//---MARKER---' lines.
12*cdf0e10cSrcweir# <dir1> .. <dirn>  Sequence of directories to run dmake in to test if the
13*cdf0e10cSrcweir#                   modification works
14*cdf0e10cSrcweir#
15*cdf0e10cSrcweir# Examples:
16*cdf0e10cSrcweir#
17*cdf0e10cSrcweir# pchdelta.py inc/pch/precompiled_sfx2.hxx inc source/dialog
18*cdf0e10cSrcweir#
19*cdf0e10cSrcweir#  Run pchdelta inside sfx2 first building the pch files and then files in
20*cdf0e10cSrcweir# source/dialog
21*cdf0e10cSrcweir#
22*cdf0e10cSrcweir# ------------------------------------------------------------------------------
23*cdf0e10cSrcweir
24*cdf0e10cSrcweirimport os
25*cdf0e10cSrcweirimport os.path
26*cdf0e10cSrcweirimport sys
27*cdf0e10cSrcweir
28*cdf0e10cSrcweir# C++
29*cdf0e10cSrcweirMARKER="//---MARKER---\n"
30*cdf0e10cSrcweir
31*cdf0e10cSrcweir# dmake
32*cdf0e10cSrcweir#MARKER="#---MARKER---\n"
33*cdf0e10cSrcweir
34*cdf0e10cSrcweir# ------------------------------------------------------------------------------
35*cdf0e10cSrcweir# Sequentially build all argument directories from scratch
36*cdf0e10cSrcweir
37*cdf0e10cSrcweirdef testSequenceBuild(dirlist):
38*cdf0e10cSrcweir    cwd = os.path.abspath(os.getcwd())
39*cdf0e10cSrcweir    for path in dirlist:
40*cdf0e10cSrcweir        os.chdir(path)
41*cdf0e10cSrcweir        buildcommand = "dmake -u"
42*cdf0e10cSrcweir        buildcommand += " >>" + cwd + "/buildlog.txt 2>&1"
43*cdf0e10cSrcweir        buildresult = os.system(buildcommand)
44*cdf0e10cSrcweir        os.chdir(cwd)
45*cdf0e10cSrcweir        if buildresult != 0:
46*cdf0e10cSrcweir            return False
47*cdf0e10cSrcweir    return True
48*cdf0e10cSrcweir
49*cdf0e10cSrcweir# ------------------------------------------------------------------------------
50*cdf0e10cSrcweir# Dump out the delta file with corresponding markers
51*cdf0e10cSrcweir
52*cdf0e10cSrcweirdef writePch(pchname, header, footer, acceptedlines, testlines):
53*cdf0e10cSrcweir    outputfile = file(pchname, "w")
54*cdf0e10cSrcweir    outputfile.write(header)
55*cdf0e10cSrcweir    outputfile.write(MARKER)
56*cdf0e10cSrcweir    outputfile.write("\n".join(acceptedlines))
57*cdf0e10cSrcweir    if len(testlines) > 0:
58*cdf0e10cSrcweir        outputfile.write("\n\n//---Candidate marker---\n")
59*cdf0e10cSrcweir        outputfile.write("\n".join(testlines) + "\n")
60*cdf0e10cSrcweir        outputfile.write("//---Candidate marker end---\n")
61*cdf0e10cSrcweir    outputfile.write(MARKER)
62*cdf0e10cSrcweir    outputfile.write(footer)
63*cdf0e10cSrcweir    outputfile.close()
64*cdf0e10cSrcweir
65*cdf0e10cSrcweir
66*cdf0e10cSrcweir# ------------------------------------------------------------------------------
67*cdf0e10cSrcweir# Recursive tester routine. Test the segment given and if an error is
68*cdf0e10cSrcweir# encountered splits the segment into <fanout> subsegment and recurses. Failing
69*cdf0e10cSrcweir# one liners are rejected. The set of accepted lines are built sequentially from
70*cdf0e10cSrcweir# the beginning.
71*cdf0e10cSrcweir
72*cdf0e10cSrcweirdef binaryTest(dirlist, lines, pchname, header, footer, acceptedlines, indent, startpoint):
73*cdf0e10cSrcweir    linecount = len(lines)
74*cdf0e10cSrcweir    if linecount == 0:
75*cdf0e10cSrcweir        return
76*cdf0e10cSrcweir    # Test if this slice passes the buildtest
77*cdf0e10cSrcweir    writePch(pchname, header, footer, acceptedlines, lines)
78*cdf0e10cSrcweir    if testSequenceBuild(dirlist):
79*cdf0e10cSrcweir        return acceptedlines + lines
80*cdf0e10cSrcweir
81*cdf0e10cSrcweir    # Reject one liners
82*cdf0e10cSrcweir    if linecount == 1:
83*cdf0e10cSrcweir        print indent + "Rejected: " + lines[0]
84*cdf0e10cSrcweir        return acceptedlines
85*cdf0e10cSrcweir
86*cdf0e10cSrcweir    # Recurse with multiline slices
87*cdf0e10cSrcweir    fanout = 4
88*cdf0e10cSrcweir    splits = []
89*cdf0e10cSrcweir    for i in range(3):
90*cdf0e10cSrcweir        splits.append(linecount * (i + 1) / fanout)
91*cdf0e10cSrcweir    splits.append(linecount)
92*cdf0e10cSrcweir
93*cdf0e10cSrcweir    splitstart = 0
94*cdf0e10cSrcweir    for splitend in splits:
95*cdf0e10cSrcweir        # avoid splitting in case we have no resulting lines
96*cdf0e10cSrcweir        if (splitend - splitstart) == 0:
97*cdf0e10cSrcweir            continue
98*cdf0e10cSrcweir        splitslice = lines[splitstart:splitend]
99*cdf0e10cSrcweir        print indent + "[" + str(startpoint + splitstart) + ":" + str(startpoint + splitend) + "] (" + str(splitend - splitstart) + ")"
100*cdf0e10cSrcweir        acceptedlines = binaryTest(dirlist, splitslice, pchname, header, footer, acceptedlines, indent + " ", startpoint + splitstart)
101*cdf0e10cSrcweir        splitstart = splitend
102*cdf0e10cSrcweir
103*cdf0e10cSrcweir    return acceptedlines
104*cdf0e10cSrcweir
105*cdf0e10cSrcweir# ------------------------------------------------------------------------------
106*cdf0e10cSrcweir# Main entry point
107*cdf0e10cSrcweir
108*cdf0e10cSrcweirif len(sys.argv) < 3:
109*cdf0e10cSrcweir    print "Usage: " + sys.argv[0] + " <pch_target> <dir1> [<dir2> <dir3> ...]"
110*cdf0e10cSrcweir    sys.exit(1)
111*cdf0e10cSrcweir
112*cdf0e10cSrcweirpchname = os.path.abspath(sys.argv[1])
113*cdf0e10cSrcweirdirlist = sys.argv[2:]
114*cdf0e10cSrcweir
115*cdf0e10cSrcweir# remove old build log file
116*cdf0e10cSrcweirif os.path.exists("buildlog.txt"):
117*cdf0e10cSrcweir    os.remove("buildlog.txt")
118*cdf0e10cSrcweir
119*cdf0e10cSrcweir# test for corner case of everything working from the start
120*cdf0e10cSrcweirif testSequenceBuild(dirlist):
121*cdf0e10cSrcweir    print "pch working, nothing to do."
122*cdf0e10cSrcweir    sys.exit(0)
123*cdf0e10cSrcweir
124*cdf0e10cSrcweir# Open the header file for reading
125*cdf0e10cSrcweirinputfile = file(pchname, "r+")
126*cdf0e10cSrcweirinputdata = inputfile.read()
127*cdf0e10cSrcweirinputfile.close()
128*cdf0e10cSrcweir
129*cdf0e10cSrcweirsegments = inputdata.split(MARKER)
130*cdf0e10cSrcweirheader = segments[0]
131*cdf0e10cSrcweirfooter = segments[2]
132*cdf0e10cSrcweirlines = segments[1].split("\n")
133*cdf0e10cSrcweir
134*cdf0e10cSrcweirwritePch(pchname + "_backup", header, footer, lines, [])
135*cdf0e10cSrcweir
136*cdf0e10cSrcweir# test for corner case of no convergence possible
137*cdf0e10cSrcweirwritePch(pchname, header, footer, [], [])
138*cdf0e10cSrcweirif not testSequenceBuild(dirlist):
139*cdf0e10cSrcweir    writePch(pchname, header, footer, lines, [])
140*cdf0e10cSrcweir    print "Building with no candidate lines failed. Convergence questionable, aborting."
141*cdf0e10cSrcweir    sys.exit(0)
142*cdf0e10cSrcweir
143*cdf0e10cSrcweir# Starting pruning
144*cdf0e10cSrcweirprint "Starting evaluation of " + str(len(lines)) + " lines"
145*cdf0e10cSrcweiracceptedlines = binaryTest(dirlist, lines, pchname, header, footer, [], "", 0)
146*cdf0e10cSrcweirwritePch(pchname, header, footer, acceptedlines, [])
147*cdf0e10cSrcweir
148*cdf0e10cSrcweir
149*cdf0e10cSrcweir
150