#!/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