#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
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;
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)
&& 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;
}
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)
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;
}
-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)
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
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)
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;
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;
/* 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);
}