From: erg Date: Tue, 19 May 2009 22:32:06 +0000 (+0000) Subject: Fix agwrite() to catch write errors and return EOF in that case. X-Git-Tag: LAST_LIBGRAPH~32^2~2041 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f43397af6ff6659532ac8263c5ac1f9da2c521b;p=graphviz Fix agwrite() to catch write errors and return EOF in that case. --- diff --git a/lib/cgraph/write.c b/lib/cgraph/write.c index 0a8df64d1..571553e66 100644 --- a/lib/cgraph/write.c +++ b/lib/cgraph/write.c @@ -20,25 +20,27 @@ #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 "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); }