after the plugins so that plugins are available to be statically linked.
tclpkg/ is suitable, but now it is misnamed since it is not just tcl anymore .... oh well.
It has the advantage that gv can share the same pkgIndex.tcl construction mechanism
for its tcl binding.
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/lib/gvc \
+ -I$(top_srcdir)/lib/common \
+ -I$(top_srcdir)/lib/graph \
+ -I$(top_srcdir)/lib/cdt \
+ -I$(top_srcdir)/lib/pathplan @PERL_INCLUDES@ @PYTHON_INCLUDES@ @RUBY_INCLUDES@ @TCL_INCLUDES@
+
+LIBS = @LIBS@ -lc
+
+if DISABLE_GVRENDER
+BASELIBS = \
+ $(top_builddir)/lib/common/libcommon.la \
+ $(top_builddir)/lib/gvc/libgvc.la @LIBGEN_LIBS@
+else
+BASELIBS = \
+ $(top_builddir)/lib/common/libcommon.la \
+ $(top_builddir)/lib/gvc/libgvc.la \
+ $(top_builddir)/plugin/cairo/libgvplugin_cairo.la \
+ $(top_builddir)/plugin/gd/libgvplugin_gd.la \
+ $(top_builddir)/plugin/text/libgvplugin_text.la \
+ $(top_builddir)/plugin/layout/libgvplugin_layout.la @CAIRO_LIBS@ @LIBGEN_LIBS@
+endif
+
+noinst_HEADERS = gv.h
+
+pkglib_LTLIBRARIES =
+pkglib_DATA =
+if WITH_SWIG
+if WITH_PERL
+pkglib_LTLIBRARIES += libgv_perl.la
+pkglib_DATA += gv.pm
+endif
+if WITH_PYTHON
+pkglib_LTLIBRARIES += libgv_python.la
+pkglib_DATA += gv.py
+endif
+if WITH_RUBY
+pkglib_LTLIBRARIES += libgv_ruby.la
+endif
+if WITH_TCL
+pkglib_LTLIBRARIES += libgv_tcl.la
+endif
+endif
+
+libgv_perl_la_SOURCES = gv.cpp gv_perl.cpp plugins.c
+libgv_perl_la_LIBADD = $(BASELIBS) @PERL_LIBS@
+
+libgv_python_la_SOURCES = gv.cpp gv_python.cpp plugins.c
+libgv_python_la_LIBADD = $(BASELIBS) @PYTHON_LIBS@
+
+libgv_ruby_la_SOURCES = gv.cpp gv_ruby.cpp plugins.c
+libgv_ruby_la_LIBADD = $(BASELIBS) @RUBY_LIBS@
+
+libgv_tcl_la_SOURCES = gv.cpp gv_tcl.cpp plugins.c
+libgv_tcl_la_LIBADD = $(BASELIBS) @TCL_LIBS@
+
+gv_perl.cpp gv.pm: gv.i
+ $(SWIG) -c++ -perl -o gv_perl.cpp gv.i
+
+gv_python.cpp gv.py: gv.i
+ $(SWIG) -c++ -python -o gv_python.cpp gv.i
+
+gv_ruby.cpp: gv.i
+ $(SWIG) -c++ -ruby -o gv_ruby.cpp gv.i
+
+gv_tcl.cpp: gv.i
+ $(SWIG) -c++ -tcl -namespace -o gv_tcl.cpp gv.i
+
+test: test_perl test_python test_ruby test_tcl
+
+test_perl:
+ mkdir -p perl
+ (cd perl; \
+ ln -fs ../.libs/libgv_perl.so gv.so; \
+ ln -fs ../gv.pm gv.pm; \
+ ln -fs ../hello.dot hello.dot; \
+ ln -fs ../test.pl test.pl; \
+ ./test.pl)
+
+test_python:
+ mkdir -p python
+ (cd python; \
+ ln -fs ../.libs/libgv_python.so _gv.so; \
+ ln -fs ../gv.py gv.py; \
+ ln -fs ../hello.dot hello.dot; \
+ ln -fs ../test.py test.py; \
+ PYTHONPATH=. ./test.py)
+
+test_ruby:
+ mkdir -p ruby
+ (cd ruby; \
+ ln -fs ../.libs/libgv_ruby.so gv.so; \
+ ln -fs ../hello.dot hello.dot; \
+ ln -fs ../test.rb test.rb; \
+ ./test.rb)
+
+test_tcl:
+ mkdir -p tcl
+ (cd tcl; \
+ ln -fs ../.libs/libgv_tcl.so gv.so; \
+ ln -fs ../hello.dot hello.dot; \
+ ln -fs ../test.tcl test.tcl; \
+ ./test.tcl)
+
+install-exec-hook:
+
+EXTRA_DIST = gv.i
+
+CLEANFILES = gv_perl.cpp gv.pm gv_python.cpp gv.py gv.pyc gv_ruby.cpp gv_tcl.cpp \
+ perl/* python/* ruby/* tcl/*
+
+DISTCLEANFILES =
--- /dev/null
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2004 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
+
+#include "gv.h"
+
+GVC_t *gvc;
+
+char *Info[] = {
+ "gv",
+ VERSION,
+ BUILDDATE
+};
+
+void gvinit()
+{
+ aginit();
+ agnodeattr(NULL, "label", NODENAME_ESC);
+ gvc = gvNEWcontext(Info, username());
+
+ /* configure codegens */
+ config_codegen_builtins(gvc);
+ gvplugin_builtins(gvc);
+// gvconfig(gvc, CONFIG);
+}
+
+Agraph_t *digraph(char *name)
+{
+ Agraph_t *g;
+
+ g = agopen(name, AGDIGRAPH);
+ GD_drawing(g) = NULL;
+ return g;
+}
+
+Agraph_t *digraphstrict(char *name)
+{
+ Agraph_t *g;
+
+ g = agopen(name, AGDIGRAPHSTRICT);
+ GD_drawing(g) = NULL;
+ return g;
+}
+
+Agraph_t *graph(char *name)
+{
+ Agraph_t *g;
+
+ g = agopen(name, AGRAPH);
+ GD_drawing(g) = NULL;
+ return g;
+}
+
+Agraph_t *graphstrict(char *name)
+{
+ Agraph_t *g;
+
+ g = agopen(name, AGRAPHSTRICT);
+ GD_drawing(g) = NULL;
+ return g;
+}
+
+Agraph_t *stringgraph(char *string)
+{
+ Agraph_t *g;
+
+ g = agmemread(string);
+ GD_drawing(g) = NULL;
+ return g;
+}
+
+Agraph_t *readgraph(char *filename)
+{
+ FILE *f;
+ Agraph_t *g;
+
+ f = fopen(filename, "r");
+ g = agread(f);
+ fclose(f);
+ GD_drawing(g) = NULL;
+ return g;
+}
+
+Agraph_t *graph(Agraph_t *g, char *name)
+{
+ return agsubg(g, name);
+}
+
+Agnode_t *node(Agraph_t *g, char *name)
+{
+ return agnode(g, name);
+}
+
+Agedge_t *edge(Agnode_t *t, Agnode_t *h)
+{
+ return agedge(t->graph, t, h);
+}
+
+char *set(Agraph_t *g, char *attr, char *val)
+{
+ Agsym_t *a;
+
+ a = agfindattr(g->root, attr);
+ if (val) {
+ if (!a)
+ a = agraphattr(g->root, attr, "");
+ agxset(g, a->index, val);
+ }
+ else {
+ if (a)
+ val = agxget(g, a->index);
+ else
+ val = "";
+ }
+ return val;
+}
+
+char *set(Agraph_t *g, char *attr)
+{
+ Agsym_t *a;
+
+ a = agfindattr(g->root, attr);
+ if (a)
+ return agxget(g, a->index);
+ else
+ return "";
+}
+
+char *set(Agnode_t *n, char *attr, char *val)
+{
+ Agraph_t *g;
+ Agsym_t *a;
+
+ g = n->graph->root;
+ a = agfindattr(g->proto->n, attr);
+ if (val) {
+ if (!a)
+ a = agnodeattr(g, attr, "");
+ agxset(n, a->index, val);
+ }
+ else {
+ if (a)
+ val = agxget(n, a->index);
+ else
+ val = "";
+ }
+ return val;
+}
+
+char *set(Agnode_t *n, char *attr)
+{
+ Agsym_t *a;
+
+ a = agfindattr(n->graph->root->proto->n, attr);
+ if (a)
+ return agxget(n, a->index);
+ else
+ return "";
+}
+
+char *set(Agedge_t *e, char *attr, char *val)
+{
+ Agraph_t *g;
+ Agsym_t *a;
+
+ g = e->tail->graph->root;
+ a = agfindattr(g->proto->e, attr);
+ if (val) {
+ if (!a)
+ a = agedgeattr(g, attr, "");
+ agxset(e, a->index, val);
+ }
+ else {
+ if (a)
+ val = agxget(e, a->index);
+ else
+ val = "";
+ }
+ return val;
+}
+
+char *set(Agedge_t *e, char *attr)
+{
+ Agsym_t *a;
+
+ a = agfindattr(e->tail->graph->root->proto->e, attr);
+ if (a)
+ return agxget(e, a->index);
+ else
+ return "";
+}
+
+void rm(Agraph_t *g)
+{
+ Agedge_t *e;
+
+ if (g->meta_node) {
+ for (e = agfstout(g->meta_node->graph, g->meta_node); e;
+ e = agnxtout(g->meta_node->graph, e)) {
+ rm(agusergraph(e->head));
+ }
+ if (g == g->root) {
+ agclose(g);
+ } else {
+ agdelete(g->meta_node->graph, g->meta_node);
+ }
+ } else {
+ fprintf(stderr, "subgraph has no meta_node\n");
+ }
+}
+
+void rm(Agnode_t *n)
+{
+ agdelete(n->graph, n);
+}
+
+void rm(Agedge_t *e)
+{
+ agdelete(e->head->graph->root, e);
+}
+
+static void reset_layout(Agraph_t *g)
+{
+ g = g->root;
+ if (GD_drawing(g)) { /* only cleanup once between layouts */
+ gvlayout_cleanup(gvc, g);
+ GD_drawing(g) = NULL;
+ }
+}
+
+void layout(Agraph_t *g, char *engine)
+{
+ char buf[256];
+ Agsym_t *a;
+ int rc;
+
+ g = g->root;
+ reset_layout(g); /* in case previously drawn */
+
+ rc = gvlayout_select(gvc, engine);
+ if (rc == NO_SUPPORT) {
+ fprintf(stderr, "Layout type: \"%s\" not recognized. Use one of:%s\n",
+ engine, gvplugin_list(gvc, API_layout, engine));
+ return;
+ }
+
+ gvlayout_layout(gvc, g);
+
+/* set bb attribute for basic layout.
+ * doesn't yet include margins, scaling or page sizes because
+ * those depend on the renderer being used. */
+ if (GD_drawing(g)->landscape)
+ sprintf(buf, "%d %d %d %d",
+ ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).LL.x),
+ ROUND(GD_bb(g).UR.y), ROUND(GD_bb(g).UR.x));
+ else
+ sprintf(buf, "%d %d %d %d",
+ ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y),
+ ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y));
+ if (!(a = agfindattr(g, "bb"))) {
+ a = agraphattr(g, "bb", "");
+ }
+ agxset(g, a->index, buf);
+}
+
+void writegraph(Agraph_t *g, char *filename, char *format)
+{
+ int rc;
+
+ g = g->root;
+
+ rc = gvrender_output_langname_job(gvc, format);
+ if (rc == NO_SUPPORT) {
+ fprintf(stderr, "Renderer type: \"%s\" not recognized. Use one of:%s\n",
+ format, gvplugin_list(gvc, API_render, format));
+ return;
+ }
+
+ gvc->job->output_lang = gvrender_select(gvc, gvc->job->output_langname);
+ if (!GD_drawing(g) && gvc->job->output_lang != CANONICAL_DOT) {
+ fprintf(stderr, "Layout was not done\n");
+ return;
+ }
+ gvrender_output_filename_job(gvc, filename);
+
+ emit_jobs(gvc, g);
+ gvrender_delete_jobs(gvc);
+}
--- /dev/null
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2004 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
+
+%module gv
+%{
+#include "gv.h"
+%}
+
+extern void gvinit();
+
+%init
+%{
+ gvinit();
+%}
+
+/* new graph objects */
+extern Agraph_t *stringgraph(char *string); /* from dot-formatted string */
+extern Agraph_t *readgraph(char *filename); /* from dot-formatted file */
+
+extern Agraph_t *digraphstrict(char *name); /* new empty digraphstrict */
+extern Agraph_t *graphstrict(char *name); /* new empty graphstrict */
+extern Agraph_t *digraph(char *name); /* new empty digraph */
+extern Agraph_t *graph(char *name); /* new empty graph */
+
+extern Agraph_t *graph(Agraph_t *g, char *name); /* add new empty subgraph to existing graph */
+extern Agnode_t *node(Agraph_t *g, char *name); /* add new node to existing graph */
+extern Agedge_t *edge(Agnode_t *t, Agnode_t *h); /* add new edge between existing nodes */
+
+/* set/get attribute of graph/node/edge */
+extern char *set(Agraph_t *g, char *attr, char *val=NULL);
+extern char *set(Agnode_t *n, char *attr, char *val=NULL);
+extern char *set(Agedge_t *e, char *attr, char *val=NULL);
+
+/* remove graph objects */
+extern void rm(Agraph_t *g);
+extern void rm(Agnode_t *n);
+extern void rm(Agedge_t *e);
+
+extern void layout(Agraph_t *g, char *engine);
+
+extern void writegraph(Agraph_t *g, char *filename, char *format);
--- /dev/null
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2004 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
+
+#include <stdio.h>
+
+#include "config.h"
+#include "types.h"
+#include "macros.h"
+#include "gvc.h"
+
+extern gvplugin_t gvplugin_cairo_LTX_plugin,
+ gvplugin_gd_LTX_plugin,
+ gvplugin_text_LTX_plugin,
+ gvplugin_layout_LTX_plugin;
+
+gvplugin_t *builtins[] = {
+ &gvplugin_cairo_LTX_plugin,
+ &gvplugin_gd_LTX_plugin,
+ &gvplugin_text_LTX_plugin,
+ &gvplugin_layout_LTX_plugin,
+ NULL
+};
+
--- /dev/null
+#!/usr/bin/perl
+
+use gv;
+
+$g = gv::digraph "G";
+print $g, "\n";
+print gv::set($g, "aaa", "xxx"), "\n";
+print gv::set($g, "aaa"), "\n";
+$n = gv::node $g, "hello";
+print $n, "\n";
+print gv::set($n,"label"), "\n";
+print gv::set($n, "aaa", "xxx"), "\n";
+print gv::set($n, "aaa"), "\n";
+$m = gv::node $g, "world";
+print $m, "\n";
+print gv::set($m, "aaa"), "\n";
+$e = gv::edge $n, $m;
+print $e, "\n";
+print gv::set($e, "aaa", "xxx"), "\n";
+print gv::set($e, "aaa"), "\n";
+gv::rm $e;
+gv::rm $n;
+gv::rm $m;
+gv::rm $g;
+
+$g = gv::stringgraph "digraph G {a->b}";
+print $g, "\n";
+gv::rm $g;
+
+$g = gv::readgraph "hello.dot";
+print $g, "\n";
+gv::layout($g, "dot");
+gv::writegraph($g, "hello_perl.png", "png");
+gv::rm $g;
--- /dev/null
+#!/usr/bin/python
+
+import gv
+
+g = gv.digraph("G")
+print g
+print gv.set(g,"aaa","xxx")
+print gv.set(g,"aaa")
+n = gv.node(g,"hello")
+print n
+print gv.set(n,"label")
+print gv.set(n,"aaa","xxx")
+print gv.set(n,"aaa")
+m = gv.node(g,"world")
+print m
+print gv.set(m,"aaa")
+e = gv.edge(n,m)
+print e
+print gv.set(e,"aaa","xxx")
+print gv.set(e,"aaa")
+gv.rm(e)
+gv.rm(m)
+gv.rm(n)
+gv.rm(g)
+
+g = gv.stringgraph("digraph G {a->b}")
+print g
+gv.rm(g)
+
+g = gv.readgraph("hello.dot")
+print g
+gv.layout(g, "dot")
+gv.writegraph(g, "hello_python.png", "png")
+gv.rm(g)
--- /dev/null
+#!/usr/bin/ruby
+
+require 'gv'
+
+g = Gv.digraph("G")
+print(g, "\n")
+print(Gv::set(g, "aaa", "xxx"), "\n")
+print(Gv::set(g, "aaa"), "\n")
+n = Gv.node(g,"hello")
+print(n, "\n")
+print(Gv::set(n, "label"), "\n")
+print(Gv::set(n, "aaa", "xxx"), "\n")
+print(Gv::set(n, "aaa"), "\n")
+m = Gv.node(g,"world")
+print(m, "\n")
+print(Gv::set(m, "aaa"), "\n")
+e = Gv.edge(n,m)
+print(e, "\n")
+print(Gv::set(e, "aaa", "xxx"), "\n")
+print(Gv::set(e, "aaa"), "\n")
+Gv.rm(e)
+Gv.rm(n)
+Gv.rm(m)
+Gv.rm(g)
+
+g = Gv.stringgraph("digraph G {a->b}")
+print(g, "\n")
+Gv.rm(g)
+
+g = Gv.readgraph("hello.dot")
+print(g, "\n")
+Gv.layout(g, "dot")
+Gv.writegraph(g, "hello_ruby.png", "png")
+Gv.rm(g)
--- /dev/null
+#!/usr/bin/tclsh
+
+load gv.so
+
+set g [gv::digraph G]
+puts $g
+puts [gv::set $g aaa xxx]
+puts [gv::set $g aaa]
+set sg [gv::graph $g SG]
+puts $sg
+set n [gv::node $g hello]
+puts $n
+puts [gv::set $n label]
+puts [gv::set $n aaa xxx]
+puts [gv::set $n aaa]
+set m [gv::node $g world]
+puts $m
+puts [gv::set $m aaa]
+set e [gv::edge $n $m]
+puts $e
+puts [gv::set $e aaa xxx]
+puts [gv::set $e aaa]
+gv::rm $e
+gv::rm $n
+gv::rm $m
+gv::rm $g
+
+set g [gv::stringgraph "digraph G {a->b}"]
+puts $g
+gv::rm $g
+
+set g [gv::readgraph hello.dot]
+puts $g
+gv::layout $g dot
+gv::writegraph $g hello_tcl.png png
+gv::rm $g