#!/usr/local/bin/python
"""Join a ColdC textdump from a lot of .cdc files.
Neale Pickett <zephyr@roguetrader.com>
The trick here is figuring out what has to go before what else."""
import glob, string, regsub, regex, sys, getopt
# How many percentage points until a new # is drawn?
checkpoint = 2
# An error we might throw
dependency = "dependency"
# Some globals
checkpoints = []
f = 0 # This will be a file later.
done = []
children = {}
depends = {}
textdump = 'textdump'
tree = 0
noisy = 1
index = 'src/+INDEX'
version = '1.0'
def write_bar(s):
"""Write out a status bar."""
if noisy:
sys.stdout.write('%s: [%s]\r%s: [' % (s,
'-' * (100/checkpoint),
s))
sys.stdout.flush()
def dependencies():
"""Calculate dependencies."""
func_def = regex.compile('^\(new *\)?object \([^ :]*\)\( *: *\(.*\)\)?;$')
for obj in files:
if obj in checkpoints and noisy:
sys.stdout.write('#')
sys.stdout.flush()
f = open('src/%s.cdc' % obj)
while 1:
line = f.readline()
if not line:
break
loc = func_def.match(line)
if loc != -1:
try:
deps = func_def.group(4)
if not deps:
break
deps = map(lambda o: o[1:], regsub.split(deps, ', *'))
for i in deps:
try:
children[i].append(obj)
except KeyError:
children[i] = [obj]
try:
depends[obj].append(i)
except KeyError:
depends[obj] = [i]
except 'foo':
pass
def descend(space, node, last=0):
"""Write to the file and build a nice tree in the process.
This is a recursive function, and a gnarly one at that."""
# Make sure we've already printed all the dependencies
try:
deps = depends[node]
for i in deps:
if i not in done:
raise dependency, (node, i)
except KeyError:
deps = ()
# Put this into the tree
if len(deps) > 1:
label = "%s %s" % (node, `deps`)
else:
label = node
if last:
ret = ['%s`--%s' % (space, label)]
space = space + ' '
else:
ret = ['%s|--%s' % (space, label)]
space = space + '| '
# Print to the textdump only if we haven't already
if node not in done:
# This is a pretty bogus way to do checkpoints, but at least you
# get a growing bar. In my tests, the growth isn't even that jerky.
if node in checkpoints and noisy:
sys.stdout.write('#')
sys.stdout.flush()
src = open('src/%s.cdc' % node)
f.writelines(src.readlines())
done.append(node) # Mark as done
# now print out all the kids
try:
kids = children[node]
except KeyError:
return ret
deps = []
while len(kids) > 0:
_kids = kids
kids = []
for i in _kids:
try:
if i == _kids[-1] and kids == []:
last = 1
else:
last = 0
ret = ret + descend(space, i, last)
except dependency, dnode:
if dnode[1] in _kids:
kids.append(i)
else:
if dnode[1] in deps:
raise dependency, dnode
else:
deps.append(dnode[1])
kids.append(i)
return ret
#################################################################
##
## Here is where the program starts
# Parse arguments
basename = string.split(sys.argv[0], '/')[-1]
try:
optlist, args = getopt.getopt(sys.argv[1:], 'qhtvi:o:')
except getopt.error, str:
print '%s: %s' % (basename, str)
print "Try `%s -h' for more information." % basename
sys.exit(0)
for pair in optlist:
c = pair[0][1]
if c == 'q':
noisy = 0
elif c == 't':
tree = 1
elif c == 'i':
index = pair[1]
elif c == 'o':
textdump = pair[1]
elif c == 'v':
print 'tdjoin version %s' % version
sys.exit(0)
elif c == 'h':
print 'Usage: %s [OPTIONS]' % basename
print """Merges .cdc files into a textdump
-q Shut up (don't print status)
-t Print hierarchy tree
-i [FILE] Write index to FILE instead of 'src/+INDEX'
-o [FILE] Write textdump to FILE instead of 'textdump'
-v Print version and exit
-h Print help (this) and exit
Neale Pickett <zephyr@roguetrader.com>"""
sys.exit(0)
# First, glob for all the files we need to play with
if noisy:
sys.stdout.write('Building list of files...')
sys.stdout.flush()
files = map(lambda fn: fn[4:-4], glob.glob("src/*.cdc"))
if noisy:
print ' done.'
# Set up for the status bar
# That's right, damnit, we're going to do this thing the *right* way!
num = len(files)
granularity = (checkpoint/100.0) * num
for i in range((100.0/checkpoint)):
checkpoints.append(files[num - int(round(granularity * i)) - 1])
# Calculate dependencies (build the dicts)
write_bar('Calculating dependencies')
dependencies()
if noisy:
print
# Write out the textdump and build the tree
write_bar(' Ordering and writing')
# I wait until here to do this so that the existing textdump will
# survive if we don't make it this far
f = open(textdump, 'w')
if 0:
print
for i,j in depends.items():
print '%s: %s' % (i, j)
tr = descend('', 'root', 1)
# We made it out, so print out the index. It just so happens that the
# items in done are already in the right order for this file.
f = open(index, 'w')
for i in done:
if i:
f.write(i + '\n')
f.close()
if noisy:
print
if tree:
for i in tr:
print i