Updated click-viz
Jose Vasconcellos
jvasco at verizon.net
Fri Jan 10 11:39:59 EST 2003
Here's an updated version of click-viz.
The main change is to support the 'require' keyword.
This tool takes a flattened click graph and produces
graph that can be processed by dot (see http://www.graphviz.org).
Enjoy!
Jose Vasconcellos
-------------- next part --------------
#!/usr/bin/python
#
# -*- Mode: Python; tab-width: 4 -*-
# vim:sw=4:expandtab:syntax=python:
#
# click-viz : a program to graphically visualize click scripts.
#
# The output of this program is meant to be piped to dot to
# generate a graph. Example:
# click-flatten demo.click | click-viz | dot -Tpng >demo.png
#
# Note: dot may be obtained from http://www.graphviz.org
#
# Author: Jose Vasconcellos <jvasco at bellatlantic.net>
# Copyright (C) 2002 Jose Vasconcellos
#
import sys
import re
verbose = 0
name = "stdin"
edict = {}
class token:
def __init__(self, s):
self.script = s
self.idx = 0
self.pat = re.compile(r"""
\s+ |
[#].*$ |
//.*$ |
/\*[^*]*\*/ |
(?P<id>[a-zA-Z0-9_@/]+) |
(?P<dblcolon>::) |
(?P<conn>->) |
\((?P<config>[^)]*)\) |
\[\s*(?P<port>\d+)\s*\] |
(?P<end>;)
""", re.VERBOSE | re.MULTILINE)
def gettoken(self):
global verbose
while 1:
m = self.pat.match(self.script, self.idx)
if m:
self.idx = m.end()
if m.lastgroup:
if verbose:
print "%s %s" % ( m.lastgroup, m.group(m.lastgroup) )
break
else:
break
return m
# read the script
if len(sys.argv) == 2:
s = file(sys.argv[1]).read()
else:
s = sys.stdin.read()
# tokenize it
tstream = token(s)
print "digraph %s {" % name
print "node [shape=record,height=.1]"
print "edge [arrowhead=normal,arrowtail=dot]"
#print "edge [sametail=true,samehead=true]"
#print "edge [tailport=s,headport=n]"
while 1:
m = tstream.gettoken()
if m == None:
break
if m.lastgroup != "id":
print "Syntax error: id expected (%s)" %m.group(m.lastgroup)
break
id = m.group(m.lastgroup)
m = tstream.gettoken()
if m.lastgroup == "config":
if id != "require":
print "Syntax error: invalid statement (%s)" %id
break
m = tstream.gettoken()
if m.lastgroup != "end":
print "Syntax error: ';' expected (%s)" %m.group(m.lastgroup)
break
elif m.lastgroup == "dblcolon":
m = tstream.gettoken()
elt = m.group(m.lastgroup)
m = tstream.gettoken()
if m.lastgroup != "end":
cfg = m.group(m.lastgroup)
m = tstream.gettoken()
else:
cfg = ""
if m.lastgroup != "end":
print "Syntax error: ';' expected (%s)" %m.group(m.lastgroup)
break
edict[id] = [elt, cfg, -1, -1]
else:
while m.lastgroup != "end":
if m.lastgroup == "port":
port = m.group(m.lastgroup)
m = tstream.gettoken()
else:
port = "0"
if edict[id][3] < int(port):
edict[id][3] = int(port)
str = '"' + id + '":o' + port
if m.lastgroup != "conn":
print "Syntax error: '->' expected (%s)" %m.group(m.lastgroup)
break
str = str + " -> "
m = tstream.gettoken()
if m.lastgroup == "port":
port = m.group(m.lastgroup)
m = tstream.gettoken()
else:
port = "0"
if m.lastgroup != "id":
print "Syntax error: id expected (%s)" %m.group(m.lastgroup)
break
id =m.group(m.lastgroup)
if edict[id][2] < int(port):
edict[id][2] = int(port)
print str + '"' + id + '":i' + port + ';'
m = tstream.gettoken()
# now print all the definitions
for k, v in edict.items():
if v[2] == -1 and v[3] == -1:
print '"'+k+'" [label="'+v[0]+'"];'
elif v[2] == -1:
print '"'+k+'" [label="{'+v[0]+'|{<'+ '>|<'.join(["o%d"% (i)
for i in range(v[3]+1)])+'>}}"];'
elif v[3] == -1:
print '"'+k+'" [label="{{<'+ '>|<'.join(["i%d"% (i)
for i in range(v[2]+1)])+'>}|'+v[0]+'}"];'
else:
print '"'+k+'" [label="{{<'+ '>|<'.join(["i%d"% (i)
for i in range(v[2]+1)])+'>}|'+v[0]+'|{<'+ '>|<'.join(["o%d"% (j)
for j in range(v[3]+1)])+'>}}"];'
print "}"
More information about the click
mailing list