]> granicus.if.org Git - graphviz/commitdiff
gxl2gv: replace inline stack implementation with generic API
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 5 Feb 2022 01:28:06 +0000 (12:28 +1100)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 24 Apr 2022 23:35:09 +0000 (16:35 -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/gxl2gv.c

index 47cb165a6c462c581946f285aec6fc859ad86b1a..223b5c844973c1b9f9516e5b52342b44e6da9b19 100644 (file)
@@ -12,6 +12,7 @@
 #include    "convert.h"
 #include    <cgraph/agxbuf.h>
 #include    <cgraph/exit.h>
+#include    <cgraph/stack.h>
 #include    <common/memory.h>
 #ifdef HAVE_EXPAT
 #include    <expat.h>
@@ -24,7 +25,6 @@
 #define XML_STATUS_ERROR 0
 #endif
 
-#define STACK_DEPTH    32
 #define BUFSIZE                20000
 #define SMALLBUF       1000
 #define NAMEBUF                100
@@ -115,8 +115,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;
@@ -212,26 +211,34 @@ static int isAnonGraph(const char *name)
 
 static void push_subg(Agraph_t * g)
 {
-    if (GSP == STACK_DEPTH) {
-       fprintf(stderr, "gxl2gv: Too many (> %d) nestings of subgraphs\n",
-               STACK_DEPTH);
-       graphviz_exit(1);
-    } else if (GSP == 0)
-       root = g;
-    G = Gstack[GSP++] = g;
+  // insert the new graph
+  stack_push_or_exit(&Gstack, g);
+
+  // save the root if this is the first graph
+  if (stack_size(&Gstack) == 1) {
+    root = g;
+  }
+
+  // update the top graph
+  G = g;
 }
 
 static Agraph_t *pop_subg(void)
 {
-    Agraph_t *g;
-    if (GSP == 0) {
-       fprintf(stderr, "gxl2gv: Gstack underflow in graph parser\n");
-       graphviz_exit(1);
-    }
-    g = Gstack[--GSP];
-    if (GSP > 0)
-       G = Gstack[GSP - 1];
-    return g;
+  // is the stack empty?
+  if (stack_is_empty(&Gstack)) {
+    fprintf(stderr, "gxl2gv: 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)
@@ -444,7 +451,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) {
                g = agopen((char *) id, Agdirected, &AgDefaultDisc);
            } else if (strcmp(edgeMode, "undirected") == 0) {
@@ -727,6 +734,7 @@ Agraph_t *gxl_to_gv(FILE * gxlFile)
     } while (!done);
     XML_ParserFree(parser);
     freeUserdata(udata);
+    stack_reset(&Gstack);
 
     return root;
 }