]> granicus.if.org Git - graphviz/commitdiff
graphml2gv: replace inline stack implementation with generic API
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Fri, 4 Feb 2022 07:49:15 +0000 (18:49 +1100)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 17 Apr 2022 21:27:16 +0000 (14:27 -0700)
Similar to previous changes to `gc` in 4e2875fd7376338259dcb3ccc8f029d58bdf22dd,
this replaces some duplicated functionality with the generic Graphviz stack
implementation. This removes the previously hard coded nested subgraph limit of
32. The number of supported subgraphs in now solely limited by available memory.

Gitlab: #1793

cmd/tools/graphml2gv.c

index 3bc8f856037cfdbdb5fa2b0329abd80ddf29ae71..a0e2108b3d3f4af4ab9ff6add841610daa34bea1 100644 (file)
@@ -12,6 +12,7 @@
 #include    "convert.h"
 #include    <cgraph/agxbuf.h>
 #include    <cgraph/exit.h>
+#include    <cgraph/stack.h>
 #include    <getopt.h>
 #ifdef HAVE_EXPAT
 #include    <expat.h>
@@ -21,7 +22,6 @@
 #define XML_STATUS_ERROR 0
 #endif
 
-#define STACK_DEPTH    32
 #define BUFSIZE                20000
 #define SMALLBUF       1000
 #define NAMEBUF                100
@@ -118,8 +118,7 @@ static Agraph_t *G;         /* Current graph */
 static Agnode_t *N;            /* Set if Current_class == TAG_NODE */
 static Agedge_t *E;            /* Set if Current_class == TAG_EDGE */
 
-static int GSP;
-static Agraph_t *Gstack[STACK_DEPTH];
+static gv_stack_t Gstack;
 
 typedef struct {
     Dtlink_t link;
@@ -205,26 +204,34 @@ static int isAnonGraph(const char *name) {
 
 static void push_subg(Agraph_t * g)
 {
-    if (GSP == STACK_DEPTH) {
-       fprintf(stderr, "graphml2gv: Too many (> %d) nestings of subgraphs\n",
-               STACK_DEPTH);
-       graphviz_exit(1);
-    } else if (GSP == 0)
-       root = g;
-    G = Gstack[GSP++] = g;
+  // save the root if this is the first graph
+  if (stack_is_empty(&Gstack)) {
+    root = g;
+  }
+
+  // insert the new graph
+  stack_push_or_exit(&Gstack, g);
+
+  // update the top graph
+  G = g;
 }
 
 static Agraph_t *pop_subg(void)
 {
-    Agraph_t *g;
-    if (GSP == 0) {
-       fprintf(stderr, "graphml2gv: Gstack underflow in graph parser\n");
-       graphviz_exit(1);
-    }
-    g = Gstack[--GSP];
-    if (GSP > 0)
-       G = Gstack[GSP - 1];
-    return g;
+  if (stack_is_empty(&Gstack)) {
+    fprintf(stderr, "graphml2gv: Gstack underflow in graph parser\n");
+    graphviz_exit(EXIT_FAILURE);
+  }
+
+  // pop the top graph
+  Agraph_t *g = stack_pop(&Gstack);
+
+  // update the top graph
+  if (!stack_is_empty(&Gstack)) {
+    G = stack_top(&Gstack);
+  }
+
+  return g;
 }
 
 static Agnode_t *bind_node(const char *name)
@@ -428,7 +435,7 @@ startElementHandler(void *userData, const char *name, const char **atts)
            edgeMode = atts[pos];
        }
 
-       if (GSP == 0) {
+       if (stack_is_empty(&Gstack)) {
            if (strcmp(edgeMode, "directed") == 0) {
                dir = Agdirected;
            } else if (strcmp(edgeMode, "undirected") == 0) {
@@ -777,6 +784,9 @@ int main(int argc, char **argv)
            fflush(outFile);
        }
     }
+
+    stack_reset(&Gstack);
+
     graphviz_exit(rv);
 #else
     fputs("cvtgxl: not configured for conversion from GXL to GV\n", stderr);