Skip to content

work towards solution for round tripping GV→GXL→GV

This series starts addressing #517 (closed). It solves the GV→GXL part, but not the remaining GXL→GV part.

@truenorth et al, can I get some guidance on this? I have the below sort-of obviously-wrong outstanding changes in my working directory. They lead to the interesting but useless outcome on the #517 (closed) example of a label of "<<TABLE><TR><TD>(</TD><TD>A</TD><TD>)</TD></TR></TABLE>>". I.e. the gxl2gv code correctly recognizes an HTML string, but the result is still " wrapped.

The (my) core problem here is that gxl2gv is constructing the Dot graph programmatically rather than as text. This is a good thing. But it calls agxset to add attributes. AFAICT this function assumes the attribute it is adding is a non-HTML string. There appears to be no equivalent to add an HTML string. Unpacking that a little… agxset unconditionally calls agstrdup, while in this case I want to call agstrdup_html.

Does this make sense and is my summary correct? If so, can you suggest a way around this?

diff --git cmd/tools/gxl2gv.c cmd/tools/gxl2gv.c
index f65e63fe7..573daaa8e 100644
--- cmd/tools/gxl2gv.c
+++ cmd/tools/gxl2gv.c
@@ -11,6 +11,7 @@

 #include    "convert.h"
 #include    <cgraph/agxbuf.h>
+#include    <cgraph/sprint.h>
 #ifdef HAVE_EXPAT
 #include    <expat.h>
 #include    <ctype.h>
@@ -38,6 +39,7 @@
 #define        TAG_GRAPH       0
 #define TAG_NODE       1
 #define TAG_EDGE       2
+#define TAG_HTML_STRING 3

 typedef struct slist slist;
 struct slist {
@@ -535,6 +537,8 @@ startElementHandler(void *userData, const char *name, const char **atts)
                ud->globalAttrType = TAG_EDGE;
            else if (strcmp("graph", atts[pos]) == 0)
                ud->globalAttrType = TAG_GRAPH;
+           else if (strcmp("HTML string", atts[pos]) == 0)
+               ud->globalAttrType = TAG_HTML_STRING;
        } else {
            ud->globalAttrType = TAG_NONE;
        }
@@ -636,6 +640,12 @@ static void endElementHandler(void *userData, const char *name)
        case TAG_GRAPH:
            setGraphAttr(G, name, value, ud);
            break;
+       case TAG_HTML_STRING: {
+           char *angle_wrapped = gv_sprint_or_exit("<%s>", value);
+           setAttr(name, angle_wrapped, ud);
+           free(angle_wrapped);
+           break;
+       }
        }
        free(dynbuf);
        ud->globalAttrType = TAG_NONE;

Merge request reports