Skip to content
Snippets Groups Projects
Commit 1b0f529d authored by dtc's avatar dtc
Browse files

Add declarations to help the CMUCL compiler.

Only the *psnode-index* hash should use the user supplied hash test,
all the others are internal.

Make the output stream a required argument rather than sending output
to *standard-output*.

Add a shrink :width optional to scale the graph to fit across one
page.

Add optional same-height argument to allocate the same height for each
node - can give nicer graphs.

Misc. style changes: less use of special variables, declarations to
help CMUCL, etc.
parent 1e5b6ce4
No related branches found
No related tags found
No related merge requests found
......@@ -6,9 +6,13 @@ Description:
Postscript commands that display a directed acyclic graph.
Author:
Joseph Bates. Skef put the whole thing in the PSGRPAPH package and added
functionality which allows the user to specify EQ, EQUAL, or EQUALP as the
node equivalence function. Bill made all exported symbols have stars on them.
Joseph Bates. Skef put the whole thing in the PSGRPAPH package and
added functionality which allows the user to specify EQ, EQUAL, or
EQUALP as the node equivalence function. Bill made all exported
symbols have stars on them. Douglas Crosher fixed the hash table
usage, added the shrink :width option and the same-height optional
argument, and cleaned up the source reducing special variables usage
and adding declarations for CMUCL.
Address:
Carnegie-Mellon University
......@@ -22,12 +26,10 @@ Copyright Status:
Public Domain.
Files:
psgraph.lisp, psgraph.fasl, psgraph.doc, psgraph.log, psgraph.catalog
psgraph.lisp, psgraph.doc, psgraph.catalog
How to Get:
The following unix command will copy the pertinent files into directory
<spec>.
cp /afs/cs.cmu.edu/project/clisp/library/psgraph/* <spec>
ftp://ftp2.cons.org/pub/languages/lisp/cmucl/src/contrib/psgraph/*
Portability:
Should run in any legal Common Lisp. Requires Postscript for printing.
......@@ -41,21 +43,4 @@ run through the output escaping any PS control characters. For example, if
node labels contain parentheses, your output PS file will not print.
Examples:
Skef Wholey submitted this as a reasonable example:
;;; I use this in my compiler so I can look at code trees without
;;; crawling around them in the inspector. The postsript previewer
;;; groks the generated ps file, which is bitchin' marvy.
(defun code-graph-to-file (s file &optional shrink insert)
(let ((psgraph:*fontname* "Times-Roman")
(psgraph:*fontsize* 8)
(psgraph:*second-fontname* "Times-BoldItalic")
(psgraph:*second-fontsize* 6)
(psgraph:*boxgray* "0")
(psgraph:*edgegray* "0")
(psgraph:*extra-x-spacing* 30))
(with-open-file (*standard-output* file
:direction :output
:if-exists :supersede)
(psgraph:psgraph s #'psg-children #'psg-info shrink insert #'eq))))
See psgraph.doc
Here is a brief summary of how to use the PSgrapher.
The PSgrapher is a set of Lisp routines that can be called to produce
Postscript commands to display a directed acyclic graph. It uses the same
basic algorithm as the ISI Grapher. It is slower than the ISI grapher, but
produces much prettier output than using Xdump to copy an ISI Grapher screen
image to a Postscript printer. It also allows arbitrary information to be
displayed with a node, and can print as many output pages as are necessary to
accomodate large graphs (subject to Postscript printer limits, typically one or
two thousand nodes).
The PSgrapher is small enough and easy enough to use to be included in other
systems without pain. It is also free and not copyrighted.
Copy the file /afs/cs/project/clisp/library/psgraph/psgraph.lisp to your
directory. It is written in Common Lisp, and has been tested on CMU Common
Lisp on RTs and Lucid on SUNs. All interfaces described below are exported
from the "PSGRAPH" package.
There are several useful global variables that can be modified and one function
to be called. The variables affect the style of the printed image, the
function walks a graph and produces output.
A graph is defined by a root node and a function for getting children of a
node. Nodes are named by Lisp objects, and these names are checked using a
user-supplied test function (defaults to EQUAL) for purposes of walking the
graph and topologically sorting it. Typically one uses atoms to name nodes,
for example in graphing an inheritence net one could use the class names as
node names.
Postscript commands to display a directed acyclic graph. It uses the
same basic algorithm as the ISI Grapher. It is slower than the ISI
grapher, but produces much prettier output than using Xdump to copy an
ISI Grapher screen image to a Postscript printer. It also allows
arbitrary information to be displayed with a node, and can print as
many output pages as are necessary to accomodate large graphs (subject
to Postscript printer limits, typically one or two thousand nodes).
The PSgrapher is small enough and easy enough to use to be included in
other systems without pain. It is also free and not copyrighted.
It is written in Common Lisp, and has been tested on CMU Common Lisp 18
All interfaces described below are exported from the "PSGRAPH" package.
There are several useful global variables that can be modified and one
function to be called. The variables affect the style of the printed
image, the function walks a graph and produces output.
A graph is defined by a root node and a function for getting children
of a node. Nodes are named by Lisp objects, and these names are
checked using a user-supplied test function (defaults to EQUAL) for
purposes of walking the graph and topologically sorting it. Typically
one uses atoms to name nodes, for example in graphing an inheritence
net one could use the class names as node names.
To produce a graph call the function:
(psgraph:psgraph root-node-name
(psgraph:psgraph output-stream
root-node-name
child-function
info-function
&optional (shrink nil)
&optional (insert nil)
&optional (test #'equal))
&optional (test #'equal)
&optional (same-height nil))
Root-node-name is a Lisp object naming the root of the graph (there must be
exactly one root).
Output-stream is the stream that the postscript is output to.
Root-node-name is a Lisp object naming the root of the graph (there
must be exactly one root).
Child-function takes a node name and returns a list of node names.
Info-function takes a node name and returns a list of strings. Each string
shows up as one line in the printed form of the node, with the first string
displayed in one font (determined by variables *fontname*, *fontsize*) and the
others in another font (determined by variables *second-fontname*,
*second-fontsize*). Typically the first string is just the name of the node,
eg, (string node-name).
Info-function takes a node name and returns a list of strings. Each
string shows up as one line in the printed form of the node, with the
first string displayed in one font (determined by variables
*fontname*, *fontsize*) and the others in another font (determined by
variables *second-fontname*, *second-fontsize*). Typically the first
string is just the name of the node, eg, (string node-name).
Shrink is a boolean. It defaults to nil, and in this case the graph
prints on as many pages as are needed to show the whole thing. If shrink
is t then the entire graph is squashed appropriately to fit on one page
of output.
Shrink may be NIL, T of :WIDTH. It defaults to nil, and in this case
the graph prints on as many pages as are needed to show the whole
thing. If shrink is T then the entire graph is squashed appropriately
to fit on one page of output. If shrink is :width then the width of
the graph is shrunk appropriately to fit across one page of output but
print on as many pages as necessary to show the full height of the graph.
Insert is a boolean. It defaults to nil, and in this case the generated
Postscript file contains commands to print the output. If insert is t
......@@ -61,14 +65,22 @@ in Scribe files, for example, and Scribe can decide when to print the page.
Test is a function that return whether two nodes are the same.
After loading psgraph, one can play with the various global variables, all of
which have string values (except for the two font size variables). *fontname*,
*fontsize*, *second-fontname*, *second-fontsize* are as described above. They
default to "Helvetica" in 10 point and "Helvetica-Oblique" in 8 point,
respectively. *boxgray* and *boxkind* determine how the boxes around nodes
look. *boxkind* is either "fill" or "stroke", for solid or outline boxes, and
*boxgray* is "0" for solid black, "1" for solid white, or in between. These
default to ".2" and "stroke".
Same-height is a boolean. It defaults to Nil, and in this case the
height of the node no large that necessary. If same-height is T the
same height is used for all the nodes which can improve the balance of
tree graphs.
-=-
After loading psgraph, one can play with the various global variables,
all of which have string values (except for the two font size
variables). *fontname*, *fontsize*, *second-fontname*,
*second-fontsize* are as described above. They default to "Helvetica"
in 10 point and "Helvetica-Oblique" in 8 point, respectively.
*boxgray* and *boxkind* determine how the boxes around nodes look.
*boxkind* is either "fill" or "stroke", for solid or outline boxes,
and *boxgray* is "0" for solid black, "1" for solid white, or in
between. These default to ".2" and "stroke".
Other variables:
*max-psnodes*
......@@ -85,21 +97,16 @@ Other variables:
*chunksize*
Psgraph sends its output to *standard-output*, so typically it is called
from within (with-open-file ....). For example, one might use it like this:
Psgraph sends its output to the output-stream, so typically it is
called from within (with-open-file ....). For example, one might use
it like this:
(load "psgraph.fasl")
(load "psgraph")
(setf psgraph:*boxkind* "fill")
(setf psgraph:*boxgray* ".8")
(setf psgraph:*fontsize* 8)
(setf psgraph:*second-fontsize* 6)
(defun graph (&optional (shrink t))
(with-open-file (*standard-output* "g.ps"
:direction :output
:if-exists :supersede)
(psgraph:psgraph 'A #'children #'info shrink nil #'eq)))
(defun children (x)
(cond ((eq x 'A) '(B C D))
((member x '(B C D)) '(E F G))
......@@ -109,6 +116,12 @@ from within (with-open-file ....). For example, one might use it like this:
(defun info (x)
(list (string x)))
(defun graph (&optional (shrink t))
(with-open-file (output-stream "g.ps"
:direction :output
:if-exists :supersede)
(psgraph:psgraph output-stream 'A #'children #'info shrink nil #'eq)))
Another example:
(defun code-graph-to-file (s file &optional shrink insert)
......@@ -119,7 +132,7 @@ Another example:
(psgraph:*boxgray* "0")
(psgraph:*edgegray* "0")
(psgraph:*extra-x-spacing* 30))
(with-open-file (*standard-output* file
:direction :output
:if-exists :supersede)
(with-open-file (output-stream file
:direction :output
:if-exists :supersede)
(psgraph:psgraph s #'psg-children #'psg-info shrink insert #'eq))))
This diff is collapsed.
/usr1/chiles/work/psgraph.lisp, Jul-90 10:59:13, Edit by Mkant.
Fixed shrink mode so that it scales x and y axes uniformly (e.g., aspect
ratio = 1).
/usr1/chiles/work/psgraph.lisp, 01-May-90 10:59:13, Edit by Chiles.
Made exported specials have stars.
/usr1/chiles/work/psgraph.lisp, APR 90, Edit by Skef Wholey.
;;; -- Now lives in the PSGRAPH package (instead of USER, or *package*...)
;;; with user-tweakable stuff exported.
;;; -- Node equivalence function can now be specified as EQ, EQUAL,
;;; or EQUALP.
/usr1/chiles/work/psgraph.lisp, DEC 88, Edit by Joseph Bates
Modified to include optional insert parameter to psgraph.
/usr1/chiles/work/psgraph.lisp, MAR 88, Edit by Joseph Bates
File created.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment