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