]> granicus.if.org Git - graphviz/commitdiff
Fix agwrite() to catch write errors and return EOF in that case.
authorerg <devnull@localhost>
Tue, 19 May 2009 22:32:06 +0000 (22:32 +0000)
committererg <devnull@localhost>
Tue, 19 May 2009 22:32:06 +0000 (22:32 +0000)
lib/cgraph/write.c

index 0a8df64d172f0f9932923ed62af784ecf5ea0597..571553e66580b5f37953e536e8fe04ff3b194072 100644 (file)
 
 #define EMPTY(s)               ((s == 0) || (s)[0] == '\0')
 #define MAX(a,b)     ((a)>(b)?(a):(b))
+#define CHKRV(v)     {if ((v)) return EOF;}
 
 typedef void iochan_t;
 
-static void ioput(Agraph_t * g, iochan_t * ofile, char *str)
+static int ioput(Agraph_t * g, iochan_t * ofile, char *str)
 {
-    AGDISC(g, io)->putstr(ofile, str);
-       
+    return AGDISC(g, io)->putstr(ofile, str);
+
 }
 
-static void write_body(Agraph_t * g, iochan_t * ofile);
+static int write_body(Agraph_t * g, iochan_t * ofile);
 static int Level;
 static unsigned char Attrs_not_written_flag;
 static Agsym_t *Tailport, *Headport;
 
-static void indent(Agraph_t * g, iochan_t * ofile)
+static int indent(Agraph_t * g, iochan_t * ofile)
 {
     int i;
     for (i = Level; i > 0; i--)
-       ioput(g, ofile, "\t");
+       CHKRV(ioput(g, ofile, "\t"));
+    return 0;
 }
 
 #ifndef HAVE_STRCASECMP
@@ -171,75 +173,80 @@ char *agcanonStr(char *str)
     return agstrcanon(str, getoutputbuffer(str));
 }
 
-static void _write_canonstr(Agraph_t * g, iochan_t * ofile, char *str,
-                           int chk)
+static int _write_canonstr(Agraph_t * g, iochan_t * ofile, char *str,
+                          int chk)
 {
     if (chk)
        str = agcanonStr(str);
     else
        str = _agstrcanon(str, getoutputbuffer(str));
-    ioput(g, ofile, str);
+    return ioput(g, ofile, str);
 }
 
-static void write_canonstr(Agraph_t * g, iochan_t * ofile, char *str)
+static int write_canonstr(Agraph_t * g, iochan_t * ofile, char *str)
 {
-    _write_canonstr(g, ofile, str, TRUE);
+    return _write_canonstr(g, ofile, str, TRUE);
 }
 
-static void write_dict(Agraph_t * g, iochan_t * ofile, char *name,
-                      Dict_t * dict, int top)
+static int write_dict(Agraph_t * g, iochan_t * ofile, char *name,
+                     Dict_t * dict, int top)
 {
     int cnt = 0;
     Dict_t *view;
     Agsym_t *sym, *psym;
 
-    if (!top) view = dtview(dict, NIL(Dict_t *));
-    else view = 0;
+    if (!top)
+       view = dtview(dict, NIL(Dict_t *));
+    else
+       view = 0;
     for (sym = (Agsym_t *) dtfirst(dict); sym;
         sym = (Agsym_t *) dtnext(dict, sym)) {
-               if (EMPTY(sym->defval)) {       /* try to skip empty str (default) */
-                       if (view == NIL(Dict_t *))
-                       continue;       /* no parent */
-                       psym = (Agsym_t *) dtsearch(view, sym);
-                       assert(psym);
-                       if (EMPTY(psym->defval))
-                       continue;       /* also empty in parent */
-               }
-               if (cnt++ == 0) {
-                       indent(g, ofile);
-                       ioput(g, ofile, name);
-                       ioput(g, ofile, " [");
-                       Level++;
-               } else {
-                       ioput(g, ofile, ",\n");
-                       indent(g, ofile);
-               }
-               write_canonstr(g, ofile, sym->name);
-               ioput(g, ofile, "=");
-               write_canonstr(g, ofile, sym->defval);
+       if (EMPTY(sym->defval)) {       /* try to skip empty str (default) */
+           if (view == NIL(Dict_t *))
+               continue;       /* no parent */
+           psym = (Agsym_t *) dtsearch(view, sym);
+           assert(psym);
+           if (EMPTY(psym->defval))
+               continue;       /* also empty in parent */
+       }
+       if (cnt++ == 0) {
+           CHKRV(indent(g, ofile));
+           CHKRV(ioput(g, ofile, name));
+           CHKRV(ioput(g, ofile, " ["));
+           Level++;
+       } else {
+           CHKRV(ioput(g, ofile, ",\n"));
+           CHKRV(indent(g, ofile));
+       }
+       CHKRV(write_canonstr(g, ofile, sym->name));
+       CHKRV(ioput(g, ofile, "="));
+       CHKRV(write_canonstr(g, ofile, sym->defval));
     }
     if (cnt > 0) {
-               Level--;
-               if (cnt > 1) {
-                       ioput(g, ofile, "\n");
-                       indent(g, ofile);
-               }
-               ioput(g, ofile, "];\n");
+       Level--;
+       if (cnt > 1) {
+           CHKRV(ioput(g, ofile, "\n"));
+           CHKRV(indent(g, ofile));
        }
-    if (!top) dtview(dict, view);              /* restore previous view */
+       CHKRV(ioput(g, ofile, "];\n"));
+    }
+    if (!top)
+       dtview(dict, view);     /* restore previous view */
+    return 0;
 }
 
-static void write_dicts(Agraph_t * g, iochan_t * ofile, int top)
+static int write_dicts(Agraph_t * g, iochan_t * ofile, int top)
 {
     Agdatadict_t *def;
-    if ((def = agdatadict(g,FALSE))) {
-               write_dict(g, ofile, "graph", def->dict.g, top);
-               write_dict(g, ofile, "node", def->dict.n, top);
-               write_dict(g, ofile, "edge", def->dict.e, top);
+    if ((def = agdatadict(g, FALSE))) {
+       CHKRV(write_dict(g, ofile, "graph", def->dict.g, top));
+       CHKRV(write_dict(g, ofile, "node", def->dict.n, top));
+       CHKRV(write_dict(g, ofile, "edge", def->dict.e, top));
     }
+    return 0;
 }
 
-static void write_hdr(Agraph_t * g, iochan_t * ofile, int top)
+static int write_hdr(Agraph_t * g, iochan_t * ofile, int top)
 {
     char *name, *sep, *kind, *strict;
     int root = 0;
@@ -263,29 +270,31 @@ static void write_hdr(Agraph_t * g, iochan_t * ofile, int top)
     sep = " ";
     if (!name || name[0] == LOCALNAMEPREFIX)
        sep = name = "";
-    indent(g, ofile);
-    ioput(g, ofile, strict);
+    CHKRV(indent(g, ofile));
+    CHKRV(ioput(g, ofile, strict));
 
     /* output "<kind>graph" only for root graphs or graphs with names */
     if (*name || root) {
-       ioput(g, ofile, kind);
-       ioput(g, ofile, "graph ");
+       CHKRV(ioput(g, ofile, kind));
+       CHKRV(ioput(g, ofile, "graph "));
     }
     if (name[0])
-       write_canonstr(g, ofile, name);
-    ioput(g, ofile, sep);
-    ioput(g, ofile, "{\n");
+       CHKRV(write_canonstr(g, ofile, name));
+    CHKRV(ioput(g, ofile, sep));
+    CHKRV(ioput(g, ofile, "{\n"));
     Level++;
-    write_dicts(g, ofile, top);
-       AGATTRWF(g) = TRUE;
+    CHKRV(write_dicts(g, ofile, top));
+    AGATTRWF(g) = TRUE;
+    return 0;
 }
 
-static void write_trl(Agraph_t * g, iochan_t * ofile)
+static int write_trl(Agraph_t * g, iochan_t * ofile)
 {
     NOTUSED(g);
     Level--;
-    indent(g, ofile);
-    ioput(g, ofile, "}\n");
+    CHKRV(indent(g, ofile));
+    CHKRV(ioput(g, ofile, "}\n"));
+    return 0;
 }
 
 static int irrelevant_subgraph(Agraph_t * g)
@@ -307,9 +316,11 @@ static int irrelevant_subgraph(Agraph_t * g)
                && strcmp(sdata->str[i], pdata->str[i]))
                return FALSE;
     }
-    dd = agdatadict(g,FALSE);
-       if (!dd) return TRUE;
-    if ((dtsize(dd->dict.n) > 0) || (dtsize(dd->dict.e) > 0)) return FALSE;
+    dd = agdatadict(g, FALSE);
+    if (!dd)
+       return TRUE;
+    if ((dtsize(dd->dict.n) > 0) || (dtsize(dd->dict.e) > 0))
+       return FALSE;
     return TRUE;
 }
 
@@ -361,17 +372,18 @@ static int not_default_attrs(Agraph_t * g, Agnode_t * n)
     return FALSE;
 }
 
-static void write_subgs(Agraph_t * g, iochan_t * ofile)
+static int write_subgs(Agraph_t * g, iochan_t * ofile)
 {
     Agraph_t *subg;
 
     for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
        if (irrelevant_subgraph(subg))
            continue;
-       write_hdr(subg, ofile, FALSE);
-       write_body(subg, ofile);
-       write_trl(subg, ofile);
+       CHKRV(write_hdr(subg, ofile, FALSE));
+       CHKRV(write_body(subg, ofile));
+       CHKRV(write_trl(subg, ofile));
     }
+    return 0;
 }
 
 static int write_edge_name(Agedge_t * e, iochan_t * ofile, int terminate)
@@ -383,10 +395,10 @@ static int write_edge_name(Agedge_t * e, iochan_t * ofile, int terminate)
     p = agnameof(e);
     g = agraphof(e);
     if (NOT(EMPTY(p))) {
-       ioput(g, ofile, " [key=");
-       write_canonstr(g, ofile, p);
+       CHKRV(ioput(g, ofile, " [key="));
+       CHKRV(write_canonstr(g, ofile, p));
        if (terminate)
-           ioput(g, ofile, "]");
+           CHKRV(ioput(g, ofile, "]"));
        rv = TRUE;
     } else
        rv = FALSE;
@@ -394,59 +406,67 @@ static int write_edge_name(Agedge_t * e, iochan_t * ofile, int terminate)
 }
 
 
-static void write_nondefault_attrs(void *obj, iochan_t * ofile,
-                                  Dict_t * defdict)
+static int write_nondefault_attrs(void *obj, iochan_t * ofile,
+                                 Dict_t * defdict)
 {
     Agattr_t *data;
     Agsym_t *sym;
     Agraph_t *g;
     int cnt = 0;
+    int rv;
 
     if ((AGTYPE(obj) == AGINEDGE) || (AGTYPE(obj) == AGOUTEDGE)) {
-               if (write_edge_name(obj, ofile, FALSE)) cnt++;
-       }
+       CHKRV(rv = write_edge_name(obj, ofile, FALSE));
+       if (rv)
+           cnt++;
+    }
     data = agattrrec(obj);
     g = agraphof(obj);
-    if (data) for (sym = (Agsym_t *) dtfirst(defdict); sym;
-         sym = (Agsym_t *) dtnext(defdict, sym)) {
+    if (data)
+       for (sym = (Agsym_t *) dtfirst(defdict); sym;
+            sym = (Agsym_t *) dtnext(defdict, sym)) {
            if ((AGTYPE(obj) == AGINEDGE) || (AGTYPE(obj) == AGOUTEDGE)) {
-                       if (Tailport && (sym->id == Tailport->id)) continue;
-                       if (Headport && (sym->id == Headport->id)) continue;
+               if (Tailport && (sym->id == Tailport->id))
+                   continue;
+               if (Headport && (sym->id == Headport->id))
+                   continue;
            }
            if (data->str[sym->id] != sym->defval) {
-                       if (cnt++ == 0) {
-                               indent(g, ofile);
-                               ioput(g, ofile, " [");
-                               Level++;
-                       } else {
-                               ioput(g, ofile, ",\n");
-                               indent(g, ofile);
-                       }
-                       write_canonstr(g, ofile, sym->name);
-                       ioput(g, ofile, "=");
-                       write_canonstr(g, ofile, data->str[sym->id]);
+               if (cnt++ == 0) {
+                   CHKRV(indent(g, ofile));
+                   CHKRV(ioput(g, ofile, " ["));
+                   Level++;
+               } else {
+                   CHKRV(ioput(g, ofile, ",\n"));
+                   CHKRV(indent(g, ofile));
+               }
+               CHKRV(write_canonstr(g, ofile, sym->name));
+               CHKRV(ioput(g, ofile, "="));
+               CHKRV(write_canonstr(g, ofile, data->str[sym->id]));
            }
        }
     if (cnt > 0) {
-               ioput(g, ofile, "]");
-               Level--;
+       CHKRV(ioput(g, ofile, "]"));
+       Level--;
     }
     AGATTRWF((Agobj_t *) obj) = TRUE;
+    return 0;
 }
 
-static void write_nodename(Agnode_t * n, iochan_t * ofile)
+static int write_nodename(Agnode_t * n, iochan_t * ofile)
 {
     char *name, buf[20];
     Agraph_t *g;
 
     name = agnameof(n);
     g = agraphof(n);
-    if (name)
-       write_canonstr(g, ofile, name);
-    else {
+    if (name) {
+       CHKRV(write_canonstr(g, ofile, name));
+    else {
        sprintf(buf, "_%ld_SUSPECT", AGID(n));  /* could be deadly wrong */
-       ioput(g, ofile, buf);
+       CHKRV(ioput(g, ofile, buf));
     }
+    return 0;
 }
 
 static int attrs_written(void *obj)
@@ -454,16 +474,16 @@ static int attrs_written(void *obj)
     return (AGATTRWF((Agobj_t *) obj));
 }
 
-static void write_node(Agnode_t * n, iochan_t * ofile, Dict_t * d)
+static int write_node(Agnode_t * n, iochan_t * ofile, Dict_t * d)
 {
     Agraph_t *g;
 
     g = agraphof(n);
-    indent(g, ofile);
-    write_nodename(n, ofile);
+    CHKRV(indent(g, ofile));
+    CHKRV(write_nodename(n, ofile));
     if (NOT(attrs_written(n)))
-       write_nondefault_attrs(n, ofile, d);
-    ioput(g, ofile, ";\n");
+       CHKRV(write_nondefault_attrs(n, ofile, d));
+    return ioput(g, ofile, ";\n");
 }
 
 /* node must be written if it wasn't already emitted because of
@@ -480,33 +500,34 @@ static int write_node_test(Agraph_t * g, Agnode_t * n,
     return FALSE;
 }
 
-static void write_port(Agedge_t * e, iochan_t * ofile, Agsym_t * port)
+static int write_port(Agedge_t * e, iochan_t * ofile, Agsym_t * port)
 {
     char *val;
     Agraph_t *g;
 
     if (!port)
-       return;
+       return 0;
     g = agraphof(e);
     val = agxget(e, port);
     if (val[0] == '\0')
-       return;
+       return 0;
 
-    ioput(g, ofile, ":");
-    if (aghtmlstr(val))
-       write_canonstr(g, ofile, val);
-    else {
+    CHKRV(ioput(g, ofile, ":"));
+    if (aghtmlstr(val)) {
+       CHKRV(write_canonstr(g, ofile, val));
+    else {
        char *s = strchr(val, ':');
        if (s) {
            *s = '\0';
-           _write_canonstr(g, ofile, val, FALSE);
-           ioput(g, ofile, ":");
-           _write_canonstr(g, ofile, s + 1, FALSE);
+           CHKRV(_write_canonstr(g, ofile, val, FALSE));
+           CHKRV(ioput(g, ofile, ":"));
+           CHKRV(_write_canonstr(g, ofile, s + 1, FALSE));
            *s = ':';
        } else {
-           _write_canonstr(g, ofile, val, FALSE);
+           CHKRV(_write_canonstr(g, ofile, val, FALSE));
        }
     }
+    return 0;
 }
 
 static int write_edge_test(Agraph_t * g, Agedge_t * e)
@@ -523,7 +544,7 @@ static int write_edge_test(Agraph_t * g, Agedge_t * e)
     return TRUE;
 }
 
-static void write_edge(Agedge_t * e, iochan_t * ofile, Dict_t * d)
+static int write_edge(Agedge_t * e, iochan_t * ofile, Dict_t * d)
 {
     Agnode_t *t, *h;
     Agraph_t *g;
@@ -531,20 +552,21 @@ static void write_edge(Agedge_t * e, iochan_t * ofile, Dict_t * d)
     t = AGTAIL(e);
     h = AGHEAD(e);
     g = agraphof(t);
-    indent(g, ofile);
-    write_nodename(t, ofile);
-    write_port(e, ofile, Tailport);
-    ioput(g, ofile, (agisdirected(agraphof(t)) ? " -> " : " -- "));
-    write_nodename(h, ofile);
-    write_port(e, ofile, Headport);
-    if (NOT(attrs_written(e)))
-       write_nondefault_attrs(e, ofile, d);
-    else
-       write_edge_name(e, ofile, TRUE);
-    ioput(g, ofile, ";\n");
+    CHKRV(indent(g, ofile));
+    CHKRV(write_nodename(t, ofile));
+    CHKRV(write_port(e, ofile, Tailport));
+    CHKRV(ioput(g, ofile, (agisdirected(agraphof(t)) ? " -> " : " -- ")));
+    CHKRV(write_nodename(h, ofile));
+    CHKRV(write_port(e, ofile, Headport));
+    if (NOT(attrs_written(e))) {
+       CHKRV(write_nondefault_attrs(e, ofile, d));
+    } else {
+       CHKRV(write_edge_name(e, ofile, TRUE));
+    }
+    return ioput(g, ofile, ";\n");
 }
 
-static void write_body(Agraph_t * g, iochan_t * ofile)
+static int write_body(Agraph_t * g, iochan_t * ofile)
 {
     Agnode_t *n, *prev;
     Agedge_t *e;
@@ -552,48 +574,53 @@ static void write_body(Agraph_t * g, iochan_t * ofile)
     /* int                  has_attr; */
 
     /* has_attr = (agattrrec(g) != NIL(Agattr_t*)); */
-    write_subgs(g, ofile);
-    dd = agdatadict(agroot(g),FALSE);
+    CHKRV(write_subgs(g, ofile));
+    dd = agdatadict(agroot(g), FALSE);
     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-               if (write_node_test(g, n, AGSEQ(n)))
-                       write_node(n, ofile, dd? dd->dict.n : 0);
-               prev = n;
-               for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
-                       if ((prev != aghead(e)) && write_node_test(g, aghead(e), AGSEQ(n)))  {
-                               write_node(aghead(e), ofile, dd? dd->dict.n : 0);
-                               prev = aghead(e);
-                       }
-                       if (write_edge_test(g, e))
-                               write_edge(e, ofile, dd? dd->dict.e : 0);
-               }
+       if (write_node_test(g, n, AGSEQ(n)))
+           CHKRV(write_node(n, ofile, dd ? dd->dict.n : 0));
+       prev = n;
+       for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
+           if ((prev != aghead(e))
+               && write_node_test(g, aghead(e), AGSEQ(n))) {
+               CHKRV(write_node(aghead(e), ofile, dd ? dd->dict.n : 0));
+               prev = aghead(e);
+           }
+           if (write_edge_test(g, e))
+               CHKRV(write_edge(e, ofile, dd ? dd->dict.e : 0));
+       }
     }
+    return 0;
 }
 
-static void set_attrwf(Agraph_t *g, int toplevel, int value)
+static void set_attrwf(Agraph_t * g, int toplevel, int value)
 {
     Agraph_t *subg;
-       Agnode_t *n;
-       Agedge_t *e;
+    Agnode_t *n;
+    Agedge_t *e;
 
     AGATTRWF(g) = value;
     for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
        set_attrwf(subg, FALSE, value);
     }
     if (toplevel) {
-       for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
-       AGATTRWF(n) = value;
-       for (e = agfstout(g,n); e; e = agnxtout(g,e))
-           AGATTRWF(e) = value;
+       for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+           AGATTRWF(n) = value;
+           for (e = agfstout(g, n); e; e = agnxtout(g, e))
+               AGATTRWF(e) = value;
        }
     }
 }
 
+/* agwrite:
+ * Return 0 on success, EOF on failure
+ */
 int agwrite(Agraph_t * g, void *ofile)
 {
-    Level = 0; /* re-initialize tab level */
-    set_attrwf(g,TRUE,FALSE);
-    write_hdr(g, ofile, TRUE);
-    write_body(g, ofile);
-    write_trl(g, ofile);
+    Level = 0;                 /* re-initialize tab level */
+    set_attrwf(g, TRUE, FALSE);
+    CHKRV(write_hdr(g, ofile, TRUE));
+    CHKRV(write_body(g, ofile));
+    CHKRV(write_trl(g, ofile));
     return AGDISC(g, io)->flush(ofile);
 }