GDTCLFT = $(top_srcdir)/tclpkg/gdtclft/gdtclft.c
endif
-libtcldot_la_SOURCES = tcldot.c tcldot-graphcmd.c tcldot-nodecmd.c tcldot-edgecmd.c tcldot-util.c no_builtins.c $(GDTCLFT)
+libtcldot_la_SOURCES = \
+ tcldot.c \
+ tcldot-graphcmd.c \
+ tcldot-nodecmd.c \
+ tcldot-edgecmd.c \
+ tcldot-util.c \
+ tcldot-mygets.c \
+ no_builtins.c $(GDTCLFT)
libtcldot_la_CPPFLAGS = $(AM_CPPFLAGS) -DDEMAND_LOADING=1
libtcldot_la_LDFLAGS = -no-undefined
libtcldot_la_LIBADD += $(LIBGEN_LIBS) $(MATH_LIBS)
-libtcldot_builtin_la_SOURCES = tcldot.c tcldot-graphcmd.c tcldot-nodecmd.c tcldot-edgecmd.c tcldot-util.c tcldot_builtins.c $(GDTCLFT)
+libtcldot_builtin_la_SOURCES = \
+ tcldot.c \
+ tcldot-graphcmd.c \
+ tcldot-nodecmd.c \
+ tcldot-edgecmd.c \
+ tcldot-util.c \
+ tcldot-mygets.c \
+ tcldot_builtins.c $(GDTCLFT)
libtcldot_builtin_la_CPPFLAGS = $(AM_CPPFLAGS) -DDEMAND_LOADING=1
libtcldot_builtin_la_LDFLAGS =
--- /dev/null
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/*************************************************************************
+ * Copyright (c) 2011 AT&T Intellectual Property
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: See CVS logs. Details at http://www.graphviz.org/
+ *************************************************************************/
+
+
+#include "tcldot.h"
+
+/*
+ * mygets - same api as gets for libgraph, or read for libcgraph
+ *
+ * gets one line at a time from a Tcl_Channel and places it in a user buffer
+ * up to a maximum of n characters
+ *
+ * returns pointer to obtained line in user buffer, or
+ * returns NULL when last line read from memory buffer
+ *
+ * This is probably innefficient because it introduces
+ * one more stage of line buffering during reads (at least)
+ * but it is needed so that we can take full advantage
+ * of the Tcl_Channel mechanism.
+ */
+#ifdef WITH_CGRAPH
+int mygets(void* channel, char *ubuf, int n)
+{
+ static Tcl_DString dstr;
+ static int strpos;
+ int nput;
+
+ if (!n) { /* a call with n==0 (from aglexinit) resets */
+ *ubuf = '\0';
+ strpos = 0;
+ return 0;
+ }
+
+ /*
+ * the user buffer might not be big enough to hold the line.
+ */
+ if (strpos) {
+ nput = Tcl_DStringLength(&dstr) - strpos;
+ if (nput > n) {
+ /* chunk between first and last */
+ memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), n);
+ strpos += n;
+ nput = n;
+ ubuf[n] = '\0';
+ } else {
+ /* last chunk */
+ memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), nput);
+ strpos = 0;
+ }
+ } else {
+ Tcl_DStringFree(&dstr);
+ Tcl_DStringInit(&dstr);
+ if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
+ /* probably EOF, but could be other read errors */
+ *ubuf = '\0';
+ return 0;
+ }
+ /* linend char(s) were stripped off by Tcl_Gets,
+ * append a canonical linenend. */
+ Tcl_DStringAppend(&dstr, "\n", 1);
+ if (Tcl_DStringLength(&dstr) > n) {
+ /* first chunk */
+ nput = n;
+ memcpy(ubuf, Tcl_DStringValue(&dstr), n);
+ strpos = n;
+ } else {
+ /* single chunk */
+ nput = Tcl_DStringLength(&dstr);
+ memcpy(ubuf, Tcl_DStringValue(&dstr),nput);
+ }
+ }
+ return nput;
+}
+#else
+char *mygets(char *ubuf, int n, FILE * channel)
+{
+ static Tcl_DString dstr;
+ static int strpos;
+
+ if (!n) { /* a call with n==0 (from aglexinit) resets */
+ *ubuf = '\0';
+ strpos = 0;
+ return NULL;
+ }
+
+ /*
+ * the user buffer might not be big enough to hold the line.
+ */
+ if (strpos) {
+ if (Tcl_DStringLength(&dstr) > (n + strpos)) {
+ /* chunk between first and last */
+ strncpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), n - 1);
+ strpos += (n - 1);
+ ubuf[n] = '\0';
+ } else {
+ /* last chunk */
+ strcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)));
+ strpos = 0;
+ }
+ } else {
+ Tcl_DStringFree(&dstr);
+ Tcl_DStringInit(&dstr);
+ if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
+ /* probably EOF, but could be other read errors */
+ *ubuf = '\0';
+ return NULL;
+ }
+ /* linend char(s) were stripped off by Tcl_Gets,
+ * append a canonical linenend. */
+ Tcl_DStringAppend(&dstr, "\n", 1);
+ if (Tcl_DStringLength(&dstr) >= n) {
+ /* first chunk */
+ strncpy(ubuf, Tcl_DStringValue(&dstr), n - 1);
+ strpos = n - 1;
+ ubuf[n] = '\0';
+ } else {
+ /* single chunk */
+ strcpy(ubuf, Tcl_DStringValue(&dstr));
+ }
+ }
+ return ubuf;
+
+#if 0
+ if (!n) { /* a call with n==0 (from aglexinit) resets */
+ mempos = (char *) mbuf; /* cast from FILE* required by API */
+ }
+
+ clp = to = ubuf;
+ for (i = 0; i < n - 1; i++) { /* leave room for terminator */
+ if (*mempos == '\0') {
+ if (i) { /* if mbuf doesn't end in \n, provide one */
+ *to++ = '\n';
+ } else { /* all done */
+ clp = NULL;
+ mempos = NULL;
+ }
+ break; /* last line or end-of-buffer */
+ }
+ if (*mempos == '\n') {
+ *to++ = *mempos++;
+ break; /* all done with this line */
+ }
+ *to++ = *mempos++; /* copy character */
+ }
+ *to++ = '\0'; /* place terminator in ubuf */
+ return clp;
+#endif
+}
+#endif /* WITH_CGRAPH */
return TCL_OK;
}
-/*
- * mygets - same api as gets for libgraph, or read for libcgraph
- *
- * gets one line at a time from a Tcl_Channel and places it in a user buffer
- * up to a maximum of n characters
- *
- * returns pointer to obtained line in user buffer, or
- * returns NULL when last line read from memory buffer
- *
- * This is probably innefficient because it introduces
- * one more stage of line buffering during reads (at least)
- * but it is needed so that we can take full advantage
- * of the Tcl_Channel mechanism.
- */
-#ifdef WITH_CGRAPH
-static int mygets(void* channel, char *ubuf, int n)
-{
- static Tcl_DString dstr;
- static int strpos;
- int nput;
-
- if (!n) { /* a call with n==0 (from aglexinit) resets */
- *ubuf = '\0';
- strpos = 0;
- return 0;
- }
-
- /*
- * the user buffer might not be big enough to hold the line.
- */
- if (strpos) {
- nput = Tcl_DStringLength(&dstr) - strpos;
- if (nput > n) {
- /* chunk between first and last */
- memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), n);
- strpos += n;
- nput = n;
- ubuf[n] = '\0';
- } else {
- /* last chunk */
- memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), nput);
- strpos = 0;
- }
- } else {
- Tcl_DStringFree(&dstr);
- Tcl_DStringInit(&dstr);
- if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
- /* probably EOF, but could be other read errors */
- *ubuf = '\0';
- return 0;
- }
- /* linend char(s) were stripped off by Tcl_Gets,
- * append a canonical linenend. */
- Tcl_DStringAppend(&dstr, "\n", 1);
- if (Tcl_DStringLength(&dstr) > n) {
- /* first chunk */
- nput = n;
- memcpy(ubuf, Tcl_DStringValue(&dstr), n);
- strpos = n;
- } else {
- /* single chunk */
- nput = Tcl_DStringLength(&dstr);
- memcpy(ubuf, Tcl_DStringValue(&dstr),nput);
- }
- }
- return nput;
-}
-#else
-static char *mygets(char *ubuf, int n, FILE * channel)
-{
- static Tcl_DString dstr;
- static int strpos;
-
- if (!n) { /* a call with n==0 (from aglexinit) resets */
- *ubuf = '\0';
- strpos = 0;
- return NULL;
- }
-
- /*
- * the user buffer might not be big enough to hold the line.
- */
- if (strpos) {
- if (Tcl_DStringLength(&dstr) > (n + strpos)) {
- /* chunk between first and last */
- strncpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), n - 1);
- strpos += (n - 1);
- ubuf[n] = '\0';
- } else {
- /* last chunk */
- strcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)));
- strpos = 0;
- }
- } else {
- Tcl_DStringFree(&dstr);
- Tcl_DStringInit(&dstr);
- if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
- /* probably EOF, but could be other read errors */
- *ubuf = '\0';
- return NULL;
- }
- /* linend char(s) were stripped off by Tcl_Gets,
- * append a canonical linenend. */
- Tcl_DStringAppend(&dstr, "\n", 1);
- if (Tcl_DStringLength(&dstr) >= n) {
- /* first chunk */
- strncpy(ubuf, Tcl_DStringValue(&dstr), n - 1);
- strpos = n - 1;
- ubuf[n] = '\0';
- } else {
- /* single chunk */
- strcpy(ubuf, Tcl_DStringValue(&dstr));
- }
- }
- return ubuf;
-
-#if 0
- if (!n) { /* a call with n==0 (from aglexinit) resets */
- mempos = (char *) mbuf; /* cast from FILE* required by API */
- }
-
- clp = to = ubuf;
- for (i = 0; i < n - 1; i++) { /* leave room for terminator */
- if (*mempos == '\0') {
- if (i) { /* if mbuf doesn't end in \n, provide one */
- *to++ = '\n';
- } else { /* all done */
- clp = NULL;
- mempos = NULL;
- }
- break; /* last line or end-of-buffer */
- }
- if (*mempos == '\n') {
- *to++ = *mempos++;
- break; /* all done with this line */
- }
- *to++ = *mempos++; /* copy character */
- }
- *to++ = '\0'; /* place terminator in ubuf */
- return clp;
-#endif
-}
-#endif /* WITH_CGRAPH */
-
#ifdef WITH_CGRAPH
-
Agraph_t *agread_usergets (FILE * fp, int (*usergets)(void *chan, char *buf, int bufsize))
{
Agraph_t* g;
(ClientData) mycontext, (Tcl_CmdDeleteProc *) NULL);
#endif /* TCLOBJ */
+#ifdef WITH_CGRAPH
+ mycontext->graphTblPtr = (void *) tclhandleInit("tcldot", sizeof(graph_context_t *), 10);
+#else
mycontext->graphTblPtr = (void *) tclhandleInit("graph", sizeof(Agraph_t *), 10);
mycontext->nodeTblPtr = (void *) tclhandleInit("node", sizeof(Agnode_t *), 100);
mycontext->edgeTblPtr = (void *) tclhandleInit("edge", sizeof(Agedge_t *), 100);
-
+#endif
return TCL_OK;
}
#endif
********* */
+/*
+ * mycontext - one per tcl interpreter, may support multiple graph namespaces
+ */
typedef struct {
#ifdef WITH_CGRAPH
Agdisc_t mydisc; // must be first to allow casting mydisc to mycontext
#endif
- void *graphTblPtr, *nodeTblPtr, *edgeTblPtr;
+ void *graphTblPtr;
+/* **FIXME** #ifndef WITH_CGRAPH */
+ void *nodeTblPtr, *edgeTblPtr;
+/* #endif */
Tcl_Interp *interp;
GVC_t *gvc;
} mycontext_t;
-/* Globals */
+#ifdef WITH_CGRAPH
+/*
+ * graph_context - one for each graph in a tcl interp
+ */
+typedef struct {
+ Agraph_t *g; /* the graph */
+ mycontext_t *mycontext; /* refer back to top context */
+} graph_context_t;
+#endif
#if HAVE_LIBGD
extern void *GDHandleTable;
extern void listGraphAttrs (Tcl_Interp * interp, Agraph_t* g);
extern void listNodeAttrs (Tcl_Interp * interp, Agraph_t* g);
extern void listEdgeAttrs (Tcl_Interp * interp, Agraph_t* g);
+extern int mygets(void* channel, char *ubuf, int n);
#else
extern void deleteEdges(mycontext_t * mycontext, Agraph_t * g, Agnode_t * n);
extern void deleteNodes(mycontext_t * mycontext, Agraph_t * g);
extern void listGraphAttrs (Tcl_Interp * interp, Agraph_t* g);
extern void listNodeAttrs (Tcl_Interp * interp, Agraph_t* g);
extern void listEdgeAttrs (Tcl_Interp * interp, Agraph_t* g);
+extern char *mygets(char *ubuf, int n, FILE * channel);
#endif
extern void setgraphattributes(Agraph_t * g, char *argv[], int argc);
extern void reset_layout(GVC_t *gvc, Agraph_t * sg);
-
-
-
-
-
-