From: erg Date: Thu, 30 Jul 2009 21:51:16 +0000 (+0000) Subject: Make xdot into a first-class library X-Git-Tag: LAST_LIBGRAPH~32^2~1766 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a0f8b017af8cdb50d6096e9e017ad5162af5de4;p=graphviz Make xdot into a first-class library --- diff --git a/configure.ac b/configure.ac index 744c8154b..58f1f606f 100644 --- a/configure.ac +++ b/configure.ac @@ -3044,6 +3044,7 @@ AC_CONFIG_FILES(Makefile lib/gvc/Makefile lib/gvc/libgvc.pc lib/xdot/Makefile + lib/xdot/libxdot.pc lib/topfish/Makefile lib/glcomp/Makefile macosx/Info.plist diff --git a/lib/xdot/Makefile.am b/lib/xdot/Makefile.am index b4b39eaeb..f1e6462d5 100644 --- a/lib/xdot/Makefile.am +++ b/lib/xdot/Makefile.am @@ -1,17 +1,34 @@ # $Id$ $Revision$ # ## Process this file with automake to produce Makefile.in -AM_CPPFLAGS = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/cgraph \ - -I$(top_srcdir)/lib/cdt - -if WITH_SMYRNA -noinst_HEADERS = xdot.h +pkgconfigdir = $(libdir)/pkgconfig + +XDOT_VERSION="1:2:0" + +pdfdir = $(pkgdatadir)/doc/pdf +pkginclude_HEADERS = xdot.h + noinst_LTLIBRARIES = libxdot_C.la -endif +lib_LTLIBRARIES = libxdot.la +pkgconfig_DATA = libxdot.pc + +man_MANS = xdot.3 +pdf_DATA = xdot.3.pdf + +#AM_CPPFLAGS = \ +# -I$(top_srcdir) \ +# -I$(top_srcdir)/lib/common \ +# -I$(top_srcdir)/lib/cgraph \ +# -I$(top_srcdir)/lib/cdt libxdot_C_la_SOURCES = xdot.c +libxdot_la_LDFLAGS = -version-info $(XDOT_VERSION) -no-undefined +libxdot_la_SOURCES = $(libxdot_C_la_SOURCES) + +xdot.3.pdf: $(srcdir)/xdot.3 + - @GROFF@ -Tps -man $(srcdir)/xdot.3 | @PS2PDF@ - - >xdot.3.pdf + +EXTRA_DIST = xdot.vcproj $(pdf_DATA) + +DISTCLEANFILES = $(pdf_DATA) -EXTRA_DIST = xdot.vcproj diff --git a/lib/xdot/xdot.3 b/lib/xdot/xdot.3 new file mode 100644 index 000000000..56b798995 --- /dev/null +++ b/lib/xdot/xdot.3 @@ -0,0 +1,203 @@ +.TH LIBXDOT 3 "31 JULY 2009" +.SH NAME +\fBlibxdot\fR \- parsing and deparsing of xdot operations +.SH SYNOPSIS +.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i +.PP +.nf +\f5 +#include + +typedef enum { + xd_left, xd_center, xd_right +} xdot_align; + +typedef struct { + double x, y, z; +} xdot_point; + +typedef struct { + double x, y, w, h; +} xdot_rect; + +typedef struct { + int cnt; + xdot_point* pts; +} xdot_polyline; + +typedef struct { + double x, y; + xdot_align align; + double width; + char* text; +} xdot_text; + +typedef struct { + xdot_rect pos; + char* name; +} xdot_image; + +typedef struct { + double size; + char* name; +} xdot_font; + +typedef enum { + xd_filled_ellipse, xd_unfilled_ellipse, + xd_filled_polygon, xd_unfilled_polygon, + xd_filled_bezier, xd_unfilled_bezier, + xd_polyline, xd_text, + xd_fill_color, xd_pen_color, xd_font, xd_style, xd_image +} xdot_kind; + +typedef enum { + xop_ellipse, + xop_polygon, + xop_bezier, + xop_polyline, xop_text, + xop_fill_color, xop_pen_color, xop_font, xop_style, xop_image +} xop_kind; + +typedef struct _xdot_op xdot_op; +typedef void (*drawfunc_t)(xdot_op*, int); +typedef void (*freefunc_t)(xdot_op*); + +struct _xdot_op { + xdot_kind kind; + union { + xdot_rect ellipse; /* xd_filled_ellipse, xd_unfilled_ellipse */ + xdot_polyline polygon; /* xd_filled_polygon, xd_unfilled_polygon */ + xdot_polyline polyline; /* xd_polyline */ + xdot_polyline bezier; /* xd_filled_bezier, xd_unfilled_bezier */ + xdot_text text; /* xd_text */ + xdot_image image; /* xd_image */ + char* color; /* xd_fill_color, xd_pen_color */ + xdot_font font; /* xd_font */ + char* style; /* xd_style */ + } u; + drawfunc_t drawfunc; +}; + +#define XDOT_PARSE_ERROR 1 + +typedef struct { + int cnt; + int sz; + xdot_op* ops; + freefunc_t freefunc; + int flags; +} xdot; + +xdot* parseXDotF (char*, drawfunc_t opfns[], int sz); +xdot* parseXDot (char*); +char* sprintXDot (xdot*); +void fprintXDot (FILE*, xdot*); +void freeXDot (xdot*); +\fP +.fi +.SH DESCRIPTION +\fIlibxdot\fP provides support for parsing and deparsing +graphical operations specificed by the \fIxdot\fP language. +.SS "Types" +.PP +.SS " xdot" +This encapsulates a series of \fIcnt\fP xdot operations, stored +in the array pointed to by \fIops\fP. The \fIsz\fP indicates +the size of each item stored in \fIops\fP. If the user sets +the \fIfreefunc\fP field, this function will be called on each +item in \fIops\fP during \fIfreeXDot\fP before the library does +its own clean up of the item. This allows the user to free any +resources stored in the item by using an expansion of the \fIxdot_op\fP +structure. +.PP +.SS " xdot_op" +A value of this type represents one xdot operation. The operation +is specified by the \fIkind\fP field. The corresponding data is +stored in the union \fIu\fP, with the subfield associated with +a given \fIkind\fP indicated by the comments. +.PP +The \fIdrawfunc\fP field allows the user to attach a drawing-specific +function to the operation, providing an object-based interface. These +functions can be automatically attached during parsing by providing a +non-NULL second argument to \fIparseXDotF\fP. +.PP +.SS " xop_kind" +This type provides an enumeration of the allowed xdot operations. +See +.br + http://www.graphviz.org/doc/info/output.html#d:xdot +.br +for the specific semantics associated with each operation. +.PP +.SS " xdot_rect" +This represents a rectangle. For ellipses, +the \fIx\fP and \fIx\fP fields represent the center of the rectangle, +and \fIw\fP and \fIh\fP give the half-width and half-height, respectively. +For images, (\fIx\fP,\fIy\fP) gives the lower left corner of the +rectangle, and \fIw\fP and \fIh\fP give the width and height, respectively. +.PP +.SS " xdot_polyline" +This type encapsulates a series of \fIcnt\fP points. +.PP +.SS " xdot_text" +A value of this type corresponds to printing the string \fItext\fP +using the baseline point (\fIx\fP,\fIy\fP). +The \fIwidth\fP field gives an approximation of how wide the printed +string will be using the current font and font size. +The \fIalign\fP field indicates how the text should be horizontally +aligned with the point (\fIx\fP,\fIy\fP). +.PP +.SS " xdot_image" +This denotes the insertion of an image. The image source is +given by \fIname\fP. The images is to be placed into the rectangle +\fIpos\fP. +.PP +.SS " xdot_font" +The fields give the name and size, in points, of a font. +.PP +.SS " xdot_align" +This enumeration type corresponds to the xdot alignment values +-1, 0 and 1 used with the text operator, or '\\l', '\\n' and '\\r' +used in dot text. +.SS "Functions" +.PP +.SS " xdot* parseXDotF (char *str, drawfunc_t* opfns, int sz)" +Parses the string \fIstr\fP as a sequence of xdot operations +and returns a pointer to the resulting \fIxdot\fP structure. +The function parses as many xdot operations as it can. If some +unknown or incorrect input was encountered in \fIstr\fP, +the \fIops\fP and \fIcnt\fP fields will reflect the operations +parsed before the error, and +the \fIXDOT_PARSE_ERROR\fP bit will be set in the \fIflags\fP field. +The function returns NULL if it cannot parse anything. +.PP +If \fIsz\fP is non-zero, it is assumed to be the size of some +structure type containing \fIxdot_op\fP as a prefix. In this case, +the elements in the array pointed to by \fIops\fP will each have +size \fIsz\fP. +.PP +If \fIopfns\fP is non-zero, it is taken to be any array of functions +indexed by \fIxop_kind\fP. During parsing, the \fIdrawfunc\fP member +of \fIxop_op\fP will be set to the corresponding function in \fIopfns\fP. +.PP +.SS " xdot* parseXDot (char *str)" +This is equivalent to \fIparseXDotF(str, 0, 0)\fP . +.PP +.SS " void freeXDot (xdot* xp)" +This frees the resources associated with the argument. +If \fIxp\fP is NULL, nothing happens. +.PP +.SS " extern char* sprintXDot (xdot* xp)" +.SS " extern void fprintXDot (FILE* fp, xdot* xp)" +These two functions deparse the argument xdot structure, producing +a string representation. \fIfprintXDot\fP writes the output onto +the open stream \fIfp\fP; \fIsprintXDot\fP returns a heap-allocated +string. + +.SH BUGS +Although some small checking is done on the \fIsz\fP argument to +\fIparseXDotF\fP, it is assumed it is a valid value from \fIsizeof\fP +applied to some structure type containing \fIxdot_op\fP as its first +field. There can be no validation of the \fIopfns\fP argument. +.SH AUTHORS +Emden R. Gansner (erg@research.att.com). diff --git a/lib/xdot/xdot.c b/lib/xdot/xdot.c index 21277be74..0080b8c84 100755 --- a/lib/xdot/xdot.c +++ b/lib/xdot/xdot.c @@ -13,187 +13,246 @@ * AT&T Research, Florham Park NJ * **********************************************************/ - #include -#include #include #include #include -#include -#include -#include -#include -static char* -parseReal (char* s, double* fp) +#define NEW(t) (t*)malloc(sizeof(t)) +#define N_NEW(n,t) (t*)malloc((n)*sizeof(t)) + +/* the parse functions should return NULL on error */ +static char *parseReal(char *s, double *fp) { - char* p; - double d; + char *p; + double d; d = strtod(s, &p); - assert (p != s); + if (p == s) return 0; + *fp = d; return (p); } -static char* -parseInt (char* s, int* ip) +static char *parseInt(char *s, int *ip) { int r, sz; r = sscanf(s, "%d%n", ip, &sz); - assert (r == 1); - return (s+sz); + if (r != 1) return 0; + else return (s + sz); } -static char* -parsePoint (char* s, xdot_point* pp) +static char *parsePoint(char *s, xdot_point * pp) { int r, sz; r = sscanf(s, "%lf %lf%n", &(pp->x), &(pp->y), &sz); - assert (r == 2); - pp->z = 0; - return (s+sz); + if (r != 2) return 0; + pp->z = 0; + return (s + sz); } -static char* -parseRect (char* s, xdot_rect* rp) +static char *parseRect(char *s, xdot_rect * rp) { int r, sz; - r = sscanf(s, "%lf %lf %lf %lf%n", &(rp->x), &(rp->y), &(rp->w), &(rp->h), &sz); - assert (r == 4); - return (s+sz); + r = sscanf(s, "%lf %lf %lf %lf%n", &(rp->x), &(rp->y), &(rp->w), + &(rp->h), &sz); + if (r != 4) return 0; + else return (s + sz); } -static char* -parsePolyline (char* s, xdot_polyline* pp) +static char *parsePolyline(char *s, xdot_polyline * pp) { int i; - xdot_point* pts; + xdot_point *pts; - s = parseInt (s, &i); + s = parseInt(s, &i); + if (!s) return s; pts = N_NEW(i, xdot_point); pp->cnt = i; - for (i = 0; i < pp->cnt; i++) - s = parsePoint (s, pts+i); + for (i = 0; i < pp->cnt; i++) { + s = parsePoint(s, pts + i); + if (!s) { + free (pts); + return 0; + } + } pp->pts = pts; return s; } -static char* -parseString (char* s, char** sp) +static char *parseString(char *s, char **sp) { int i; - char* c; - s = parseInt (s, &i); - c = N_NEW(i+1, char); - while (*s++ != '-'); - memcpy (c, s, i); - c[i] = '\0'; + char *c; + char *p; + s = parseInt(s, &i); + if (!s || (i <= 0)) return 0; + while (*s && (*s != '-')) s++; + if (*s) s++; + else { + return 0; + } + c = N_NEW(i + 1, char); + p = c; + while ((i > 0) && *s) { + *p++ = *s++; + i--; + } + if (i > 0) { + free (c); + return 0; + } + + *p = '\0'; *sp = c; - return (s+i); + return s; } -static char* -parseAlign (char* s, xdot_align* ap) +static char *parseAlign(char *s, xdot_align * ap) { int i; - s = parseInt (s, &i); - if (i < 0) *ap = xd_left; - else if (i > 0) *ap = xd_right; - else *ap = xd_center; + s = parseInt(s, &i); + + if (i < 0) + *ap = xd_left; + else if (i > 0) + *ap = xd_right; + else + *ap = xd_center; return s; } -static char* -parseOp (xdot_op* op, char* s, drawfunc_t ops[]) +#define CHK(s) if(!s){*error=1;return 0;} + +static char *parseOp(xdot_op * op, char *s, drawfunc_t ops[], int* error) { - while (isspace(*s)) s++; + *error = 0; + while (isspace(*s)) + s++; switch (*s++) { - case 'E' : + case 'E': op->kind = xd_filled_ellipse; - s = parseRect (s, &op->u.ellipse); - if (ops) op->drawfunc=ops[xop_ellipse]; + s = parseRect(s, &op->u.ellipse); + CHK(s); + if (ops) + op->drawfunc = ops[xop_ellipse]; break; - case 'e' : + case 'e': op->kind = xd_unfilled_ellipse; - s = parseRect (s, &op->u.ellipse); - if (ops) op->drawfunc=ops[xop_ellipse]; + s = parseRect(s, &op->u.ellipse); + CHK(s); + if (ops) + op->drawfunc = ops[xop_ellipse]; break; - case 'P' : + case 'P': op->kind = xd_filled_polygon; - s = parsePolyline (s, &op->u.polygon); - if (ops) op->drawfunc=ops[xop_polygon]; + s = parsePolyline(s, &op->u.polygon); + CHK(s); + if (ops) + op->drawfunc = ops[xop_polygon]; break; - case 'p' : + case 'p': op->kind = xd_unfilled_polygon; - s = parsePolyline (s, &op->u.polygon); - if (ops) op->drawfunc=ops[xop_polygon]; + s = parsePolyline(s, &op->u.polygon); + CHK(s); + if (ops) + op->drawfunc = ops[xop_polygon]; break; - case 'b' : + case 'b': op->kind = xd_filled_bezier; - s = parsePolyline (s, &op->u.bezier); - if (ops) op->drawfunc=ops[xop_bezier]; + s = parsePolyline(s, &op->u.bezier); + CHK(s); + if (ops) + op->drawfunc = ops[xop_bezier]; break; - - case 'B' : + + case 'B': op->kind = xd_unfilled_bezier; - s = parsePolyline (s, &op->u.bezier); - if (ops) op->drawfunc=ops[xop_bezier]; + s = parsePolyline(s, &op->u.bezier); + CHK(s); + if (ops) + op->drawfunc = ops[xop_bezier]; break; - - case 'c' : + + case 'c': op->kind = xd_pen_color; - s = parseString (s, &op->u.color); - if (ops) op->drawfunc=ops[xop_pen_color]; + s = parseString(s, &op->u.color); + CHK(s); + if (ops) + op->drawfunc = ops[xop_pen_color]; break; - - case 'C' : + + case 'C': op->kind = xd_fill_color; - s = parseString (s, &op->u.color); - if (ops) op->drawfunc=ops[xop_fill_color]; + s = parseString(s, &op->u.color); + CHK(s); + if (ops) + op->drawfunc = ops[xop_fill_color]; break; - - case 'L' : + + case 'L': op->kind = xd_polyline; - s = parsePolyline (s, &op->u.polyline); - if (ops) op->drawfunc=ops[xop_polyline]; + s = parsePolyline(s, &op->u.polyline); + CHK(s); + if (ops) + op->drawfunc = ops[xop_polyline]; break; - - case 'T' : + + case 'T': op->kind = xd_text; - s = parseReal (s, &op->u.text.x); - s = parseReal (s, &op->u.text.y); - s = parseAlign (s, &op->u.text.align); - s = parseReal (s, &op->u.text.width); - s = parseString (s, &op->u.text.text); - if (ops) op->drawfunc=ops[xop_text]; - break; - - case 'F' : + s = parseReal(s, &op->u.text.x); + CHK(s); + s = parseReal(s, &op->u.text.y); + CHK(s); + s = parseAlign(s, &op->u.text.align); + CHK(s); + s = parseReal(s, &op->u.text.width); + CHK(s); + s = parseString(s, &op->u.text.text); + CHK(s); + if (ops) + op->drawfunc = ops[xop_text]; + break; + + case 'F': op->kind = xd_font; - s = parseReal (s, &op->u.font.size); - s = parseString (s, &op->u.font.name); - if (ops) op->drawfunc=ops[xop_font]; + s = parseReal(s, &op->u.font.size); + CHK(s); + s = parseString(s, &op->u.font.name); + CHK(s); + if (ops) + op->drawfunc = ops[xop_font]; break; - - case 'S' : + + case 'S': op->kind = xd_style; - s = parseString (s, &op->u.style); - if (ops) op->drawfunc=ops[xop_style]; + s = parseString(s, &op->u.style); + CHK(s); + if (ops) + op->drawfunc = ops[xop_style]; break; - - case 'I' : + + case 'I': op->kind = xd_image; - s = parseRect (s, &op->u.image.pos); - s = parseString (s, &op->u.image.name); - if (ops) op->drawfunc=ops[xop_image]; + s = parseRect(s, &op->u.image.pos); + CHK(s); + s = parseString(s, &op->u.image.name); + CHK(s); + if (ops) + op->drawfunc = ops[xop_image]; + break; + + + case '\0': + s = 0; break; - - default : + + default: + *error = 1; s = 0; break; } @@ -202,208 +261,206 @@ parseOp (xdot_op* op, char* s, drawfunc_t ops[]) #define XDBSIZE 100 -xdot* -parseXDotF (char* s, drawfunc_t fns[], int sz) +xdot *parseXDotF(char *s, drawfunc_t fns[], int sz) { - xdot* x; + xdot *x; xdot_op op; - char* ops; - int bufsz = XDBSIZE; - if (!s) return NULL; + char *ops; + int oldsz, bufsz = XDBSIZE; + int error; + + if (!s) + return NULL; x = NEW(xdot); - if (sz <= 0) sz = sizeof(xdot_op); - ops = (char*)gmalloc(XDBSIZE*sz); + if (sz <= sizeof(xdot_op)) + sz = sizeof(xdot_op); + ops = (char *) calloc(XDBSIZE, sz); x->cnt = 0; + x->flags = 0; + x->freefunc = 0; x->sz = sz; - while ((s = parseOp (&op, s, fns))) - { - if (x->cnt == bufsz) - { - bufsz += XDBSIZE; - ops = (char*)grealloc (ops, bufsz*sz); - } - *(xdot_op*)(ops + (x->cnt*sz)) = op; - x->cnt++; + while ((s = parseOp(&op, s, fns, &error))) { + if (x->cnt == bufsz) { + oldsz = bufsz; + bufsz *= 2; + ops = (char *) realloc(ops, bufsz * sz); + memset(ops + (oldsz*sz), '\0', (bufsz - oldsz)*sz); + } + *(xdot_op *) (ops + (x->cnt * sz)) = op; + x->cnt++; } - if (x->cnt) - x->ops = (xdot_op*)grealloc (ops, x->cnt*sz); - else - { - free (x); - x = 0; + if (x->cnt) { + x->ops = (xdot_op *) realloc(ops, x->cnt * sz); + if (error) + x->flags |= XDOT_PARSE_ERROR; + } + else { + free(x); + x = 0; } return x; } -xdot* -parseXDot (char* s) +xdot *parseXDot(char *s) { - return parseXDotF (s, 0, 0); + return parseXDotF(s, 0, 0); } -typedef void (*pf)(char*, void*); +typedef void (*pf) (char *, void *); -static void -printRect (xdot_rect* r, pf print, void* info) +static void printRect(xdot_rect * r, pf print, void *info) { char buf[128]; - sprintf (buf, " %.06f %.06f %.06f %.06f", r->x, r->y, r->w, r->h); - print (buf, info); + sprintf(buf, " %.06f %.06f %.06f %.06f", r->x, r->y, r->w, r->h); + print(buf, info); } -static void -printPolyline (xdot_polyline* p, pf print, void* info) +static void printPolyline(xdot_polyline * p, pf print, void *info) { int i; char buf[512]; - sprintf (buf, " %d", p->cnt); - print (buf, info); - for (i = 0; i< p->cnt; i++) { - sprintf (buf, " %.06f %.06f", p->pts[i].x, p->pts[i].y); - print (buf, info); + sprintf(buf, " %d", p->cnt); + print(buf, info); + for (i = 0; i < p->cnt; i++) { + sprintf(buf, " %.06f %.06f", p->pts[i].x, p->pts[i].y); + print(buf, info); } } -static void -printString (char* p, pf print, void* info) +static void printString(char *p, pf print, void *info) { char buf[30]; - sprintf (buf, " %d -", (int)strlen(p)); - print (buf, info); - print (p, info); + sprintf(buf, " %d -", (int) strlen(p)); + print(buf, info); + print(p, info); } -static void -printInt (int i, pf print, void* info) +static void printInt(int i, pf print, void *info) { char buf[30]; - sprintf (buf, " %d", i); - print (buf, info); + sprintf(buf, " %d", i); + print(buf, info); } -static void -printFloat (float f, pf print, void* info) +static void printFloat(float f, pf print, void *info) { char buf[128]; - sprintf (buf, " %f", f); - print (buf, info); + sprintf(buf, " %f", f); + print(buf, info); } -static void -printAlign (xdot_align a, pf print, void* info) +static void printAlign(xdot_align a, pf print, void *info) { switch (a) { - case xd_left : - print (" -1", info); + case xd_left: + print(" -1", info); break; - case xd_right : - print (" 1", info); + case xd_right: + print(" 1", info); break; - case xd_center : - print (" 0", info); + case xd_center: + print(" 0", info); break; } } -static void -printXDot_Op (xdot_op* op, pf print, void* info) +static void printXDot_Op(xdot_op * op, pf print, void *info) { switch (op->kind) { - case xd_filled_ellipse : - print ("E", info); - printRect (&op->u.ellipse, print, info); + case xd_filled_ellipse: + print("E", info); + printRect(&op->u.ellipse, print, info); break; - case xd_unfilled_ellipse : - print ("e", info); - printRect (&op->u.ellipse, print, info); + case xd_unfilled_ellipse: + print("e", info); + printRect(&op->u.ellipse, print, info); break; - case xd_filled_polygon : - print ("P", info); - printPolyline (&op->u.polygon, print, info); + case xd_filled_polygon: + print("P", info); + printPolyline(&op->u.polygon, print, info); break; - case xd_unfilled_polygon : - print ("p", info); - printPolyline (&op->u.polygon, print, info); + case xd_unfilled_polygon: + print("p", info); + printPolyline(&op->u.polygon, print, info); break; - case xd_filled_bezier : - print ("b", info); + case xd_filled_bezier: + print("b", info); op->kind = xd_filled_bezier; - printPolyline (&op->u.bezier, print, info); - break; - case xd_unfilled_bezier : - print ("B", info); - printPolyline (&op->u.bezier, print, info); - break; - case xd_pen_color : - print ("c", info); - printString (op->u.color, print, info); - break; - case xd_fill_color : - print ("C", info); - printString (op->u.color, print, info); - break; - case xd_polyline : - print ("L", info); - printPolyline (&op->u.polyline, print, info); - break; - case xd_text : - print ("T", info); - printInt (op->u.text.x, print, info); - printInt (op->u.text.y, print, info); - printAlign (op->u.text.align, print, info); - printInt (op->u.text.width, print, info); - printString (op->u.text.text, print, info); - break; - case xd_font : - print ("F", info); + printPolyline(&op->u.bezier, print, info); + break; + case xd_unfilled_bezier: + print("B", info); + printPolyline(&op->u.bezier, print, info); + break; + case xd_pen_color: + print("c", info); + printString(op->u.color, print, info); + break; + case xd_fill_color: + print("C", info); + printString(op->u.color, print, info); + break; + case xd_polyline: + print("L", info); + printPolyline(&op->u.polyline, print, info); + break; + case xd_text: + print("T", info); + printInt(op->u.text.x, print, info); + printInt(op->u.text.y, print, info); + printAlign(op->u.text.align, print, info); + printInt(op->u.text.width, print, info); + printString(op->u.text.text, print, info); + break; + case xd_font: + print("F", info); op->kind = xd_font; - printFloat (op->u.font.size, print, info); - printString (op->u.font.name, print, info); + printFloat(op->u.font.size, print, info); + printString(op->u.font.name, print, info); break; - case xd_style : - print ("S", info); - printString (op->u.style, print, info); + case xd_style: + print("S", info); + printString(op->u.style, print, info); break; - case xd_image : - print ("I", info); - printRect (&op->u.image.pos, print, info); - printString (op->u.image.name, print, info); + case xd_image: + print("I", info); + printRect(&op->u.image.pos, print, info); + printString(op->u.image.name, print, info); break; } } -static void -_printXDot (xdot* x, pf print, void* info) +static void _printXDot(xdot * x, pf print, void *info) { int i; - xdot_op* op; - char* base = (char*)(x->ops); + xdot_op *op; + char *base = (char *) (x->ops); for (i = 0; i < x->cnt; i++) { - op = (xdot_op*)(base + i*x->sz); - printXDot_Op (op, print, info); - if (i < x->cnt-1) print (" ", info); + op = (xdot_op *) (base + i * x->sz); + printXDot_Op(op, print, info); + if (i < x->cnt - 1) + print(" ", info); } } - + typedef struct { - unsigned char *buf; /* start of buffer */ - unsigned char *ptr; /* next place to write */ + unsigned char *buf; /* start of buffer */ + unsigned char *ptr; /* next place to write */ unsigned char *eptr; /* end of buffer */ - int dyna; /* true if buffer is malloc'ed */ + int dyna; /* true if buffer is malloc'ed */ } agxbuf; #define agxbputc(X,C) ((((X)->ptr >= (X)->eptr) ? agxbmore(X,1) : 0), \ (int)(*(X)->ptr++ = ((unsigned char)C))) #define agxbuse(X) (agxbputc(X,'\0'),(char*)((X)->ptr = (X)->buf)) -static void -agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init) +static void agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init) { if (init) { xb->buf = init; @@ -418,8 +475,7 @@ agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init) xb->ptr = xb->buf; *xb->ptr = '\0'; } -static int -agxbmore(agxbuf * xb, unsigned int ssz) +static int agxbmore(agxbuf * xb, unsigned int ssz) { int cnt; /* current no. of characters in buffer */ int size; /* current buffer size */ @@ -444,10 +500,9 @@ agxbmore(agxbuf * xb, unsigned int ssz) return 0; } -static int -agxbput(char* s, agxbuf * xb) +static int agxbput(char *s, agxbuf * xb) { - unsigned int ssz = strlen (s); + unsigned int ssz = strlen(s); if (xb->ptr + ssz > xb->eptr) agxbmore(xb, ssz); memcpy(xb->ptr, s, ssz); @@ -458,87 +513,86 @@ agxbput(char* s, agxbuf * xb) /* agxbfree: * Free any malloced resources. */ -static void -agxbfree(agxbuf * xb) +static void agxbfree(agxbuf * xb) { if (xb->dyna) free(xb->buf); } -char* -sprintXDot (xdot* x) +char *sprintXDot(xdot * x) { - char* s; + char *s; unsigned char buf[BUFSIZ]; agxbuf xb; - agxbinit (&xb, BUFSIZ, buf); - _printXDot (x, (pf)agxbput, &xb); - s = strdup(agxbuse (&xb)); - agxbfree (&xb); + agxbinit(&xb, BUFSIZ, buf); + _printXDot(x, (pf) agxbput, &xb); + s = strdup(agxbuse(&xb)); + agxbfree(&xb); return s; } -void -fprintXDot (FILE* fp, xdot* x) +void fprintXDot(FILE * fp, xdot * x) { - _printXDot (x, (pf)fputs, fp); + _printXDot(x, (pf) fputs, fp); } -static void -freeXOpData (xdot_op* x) +static void freeXOpData(xdot_op * x) { switch (x->kind) { - case xd_filled_polygon : - case xd_unfilled_polygon : - free (x->u.polyline.pts); + case xd_filled_polygon: + case xd_unfilled_polygon: + free(x->u.polyline.pts); break; - case xd_filled_bezier : - case xd_unfilled_bezier : - free (x->u.polyline.pts); + case xd_filled_bezier: + case xd_unfilled_bezier: + free(x->u.polyline.pts); break; - case xd_polyline : - free (x->u.polyline.pts); + case xd_polyline: + free(x->u.polyline.pts); break; - case xd_text : - free (x->u.text.text); + case xd_text: + free(x->u.text.text); break; - case xd_fill_color : - case xd_pen_color : - free (x->u.color); + case xd_fill_color: + case xd_pen_color: + free(x->u.color); break; - case xd_font : - free (x->u.font.name); + case xd_font: + free(x->u.font.name); break; - case xd_style : - free (x->u.style); + case xd_style: + free(x->u.style); break; - case xd_image : - free (x->u.image.name); + case xd_image: + free(x->u.image.name); break; - default : + default: break; } } -void -freeXDot (xdot* x) +void freeXDot (xdot * x) { int i; - xdot_op* op; - char* base = (char*)(x->ops); + xdot_op *op; + char *base; + freefunc_t ff = x->freefunc; + + if (!x) return; + base = (char *) (x->ops); for (i = 0; i < x->cnt; i++) { - op = (xdot_op*)(base + i*x->sz); - freeXOpData (op); + op = (xdot_op *) (base + i * x->sz); + if (ff) ff (op); + freeXOpData(op); } - free (base); - free (x); + free(base); + free(x); } #if 0 -static void -execOp (xdot_op* op,int param) +static void execOp(xdot_op * op, int param) { - op->drawfunc(op,param); + op->drawfunc(op, param); } #endif diff --git a/lib/xdot/xdot.h b/lib/xdot/xdot.h index ccdbe4c68..127d224a1 100755 --- a/lib/xdot/xdot.h +++ b/lib/xdot/xdot.h @@ -26,7 +26,7 @@ typedef enum { } xdot_align; typedef struct { - double x, y, z; //z is constant + double x, y, z; } xdot_point; typedef struct { @@ -73,6 +73,7 @@ typedef enum { typedef struct _xdot_op xdot_op; typedef void (*drawfunc_t)(xdot_op*, int); +typedef void (*freefunc_t)(xdot_op*); struct _xdot_op { xdot_kind kind; @@ -90,14 +91,18 @@ struct _xdot_op { drawfunc_t drawfunc; }; +#define XDOT_PARSE_ERROR 1 + typedef struct { int cnt; int sz; xdot_op* ops; + freefunc_t freefunc; + int flags; } xdot; /* ops are indexed by xop_kind */ -extern xdot* parseXDotF (char*, drawfunc_t ops[], int sz); +extern xdot* parseXDotF (char*, drawfunc_t opfns[], int sz); extern xdot* parseXDot (char*); extern char* sprintXDot (xdot*); extern void fprintXDot (FILE*, xdot*);