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: ...@@ -6,9 +6,13 @@ Description:
Postscript commands that display a directed acyclic graph. Postscript commands that display a directed acyclic graph.
Author: Author:
Joseph Bates. Skef put the whole thing in the PSGRPAPH package and added Joseph Bates. Skef put the whole thing in the PSGRPAPH package and
functionality which allows the user to specify EQ, EQUAL, or EQUALP as the added functionality which allows the user to specify EQ, EQUAL, or
node equivalence function. Bill made all exported symbols have stars on them. 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: Address:
Carnegie-Mellon University Carnegie-Mellon University
...@@ -22,12 +26,10 @@ Copyright Status: ...@@ -22,12 +26,10 @@ Copyright Status:
Public Domain. Public Domain.
Files: Files:
psgraph.lisp, psgraph.fasl, psgraph.doc, psgraph.log, psgraph.catalog psgraph.lisp, psgraph.doc, psgraph.catalog
How to Get: How to Get:
The following unix command will copy the pertinent files into directory ftp://ftp2.cons.org/pub/languages/lisp/cmucl/src/contrib/psgraph/*
<spec>.
cp /afs/cs.cmu.edu/project/clisp/library/psgraph/* <spec>
Portability: Portability:
Should run in any legal Common Lisp. Requires Postscript for printing. 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 ...@@ -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. node labels contain parentheses, your output PS file will not print.
Examples: Examples:
Skef Wholey submitted this as a reasonable example: See psgraph.doc
;;; 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))))
Here is a brief summary of how to use the PSgrapher. 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 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 Postscript commands to display a directed acyclic graph. It uses the
basic algorithm as the ISI Grapher. It is slower than the ISI grapher, but same basic algorithm as the ISI Grapher. It is slower than the ISI
produces much prettier output than using Xdump to copy an ISI Grapher screen grapher, but produces much prettier output than using Xdump to copy an
image to a Postscript printer. It also allows arbitrary information to be ISI Grapher screen image to a Postscript printer. It also allows
displayed with a node, and can print as many output pages as are necessary to arbitrary information to be displayed with a node, and can print as
accomodate large graphs (subject to Postscript printer limits, typically one or many output pages as are necessary to accomodate large graphs (subject
two thousand nodes). 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 The PSgrapher is small enough and easy enough to use to be included in
systems without pain. It is also free and not copyrighted. other systems without pain. It is also free and not copyrighted.
Copy the file /afs/cs/project/clisp/library/psgraph/psgraph.lisp to your It is written in Common Lisp, and has been tested on CMU Common Lisp 18
directory. It is written in Common Lisp, and has been tested on CMU Common All interfaces described below are exported from the "PSGRAPH" package.
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
There are several useful global variables that can be modified and one function image, the function walks a graph and produces output.
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
A graph is defined by a root node and a function for getting children of a checked using a user-supplied test function (defaults to EQUAL) for
node. Nodes are named by Lisp objects, and these names are checked using a purposes of walking the graph and topologically sorting it. Typically
user-supplied test function (defaults to EQUAL) for purposes of walking the one uses atoms to name nodes, for example in graphing an inheritence
graph and topologically sorting it. Typically one uses atoms to name nodes, net one could use the class names as node names.
for example in graphing an inheritence net one could use the class names as
node names.
To produce a graph call the function: To produce a graph call the function:
(psgraph:psgraph root-node-name (psgraph:psgraph output-stream
root-node-name
child-function child-function
info-function info-function
&optional (shrink nil) &optional (shrink nil)
&optional (insert 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 Output-stream is the stream that the postscript is output to.
exactly one root).
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. 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 Info-function takes a node name and returns a list of strings. Each
shows up as one line in the printed form of the node, with the first string string shows up as one line in the printed form of the node, with the
displayed in one font (determined by variables *fontname*, *fontsize*) and the first string displayed in one font (determined by variables
others in another font (determined by variables *second-fontname*, *fontname*, *fontsize*) and the others in another font (determined by
*second-fontsize*). Typically the first string is just the name of the node, variables *second-fontname*, *second-fontsize*). Typically the first
eg, (string node-name). 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 Shrink may be NIL, T of :WIDTH. It defaults to nil, and in this case
prints on as many pages as are needed to show the whole thing. If shrink the graph prints on as many pages as are needed to show the whole
is t then the entire graph is squashed appropriately to fit on one page thing. If shrink is T then the entire graph is squashed appropriately
of output. 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 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 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. ...@@ -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. 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 Same-height is a boolean. It defaults to Nil, and in this case the
which have string values (except for the two font size variables). *fontname*, height of the node no large that necessary. If same-height is T the
*fontsize*, *second-fontname*, *second-fontsize* are as described above. They same height is used for all the nodes which can improve the balance of
default to "Helvetica" in 10 point and "Helvetica-Oblique" in 8 point, tree graphs.
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". 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: Other variables:
*max-psnodes* *max-psnodes*
...@@ -85,21 +97,16 @@ Other variables: ...@@ -85,21 +97,16 @@ Other variables:
*chunksize* *chunksize*
Psgraph sends its output to *standard-output*, so typically it is called Psgraph sends its output to the output-stream, so typically it is
from within (with-open-file ....). For example, one might use it like this: 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:*boxkind* "fill")
(setf psgraph:*boxgray* ".8") (setf psgraph:*boxgray* ".8")
(setf psgraph:*fontsize* 8) (setf psgraph:*fontsize* 8)
(setf psgraph:*second-fontsize* 6) (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) (defun children (x)
(cond ((eq x 'A) '(B C D)) (cond ((eq x 'A) '(B C D))
((member x '(B C D)) '(E F G)) ((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: ...@@ -109,6 +116,12 @@ from within (with-open-file ....). For example, one might use it like this:
(defun info (x) (defun info (x)
(list (string 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: Another example:
(defun code-graph-to-file (s file &optional shrink insert) (defun code-graph-to-file (s file &optional shrink insert)
...@@ -119,7 +132,7 @@ Another example: ...@@ -119,7 +132,7 @@ Another example:
(psgraph:*boxgray* "0") (psgraph:*boxgray* "0")
(psgraph:*edgegray* "0") (psgraph:*edgegray* "0")
(psgraph:*extra-x-spacing* 30)) (psgraph:*extra-x-spacing* 30))
(with-open-file (*standard-output* file (with-open-file (output-stream file
:direction :output :direction :output
:if-exists :supersede) :if-exists :supersede)
(psgraph:psgraph s #'psg-children #'psg-info shrink insert #'eq)))) (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