]> granicus.if.org Git - graphviz/commitdiff
Make xdot into a first-class library
authorerg <devnull@localhost>
Thu, 30 Jul 2009 21:51:16 +0000 (21:51 +0000)
committererg <devnull@localhost>
Thu, 30 Jul 2009 21:51:16 +0000 (21:51 +0000)
configure.ac
lib/xdot/Makefile.am
lib/xdot/xdot.3 [new file with mode: 0644]
lib/xdot/xdot.c
lib/xdot/xdot.h

index 744c8154b6369f7683e80ca59c2ecc9098599bb3..58f1f606f1509c259463ec69751766d092907ea1 100644 (file)
@@ -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
index b4b39eaeb38582efddba8b0da5135b3ad9d98f54..f1e6462d578f9676e28586199cc470a32aa9deb2 100644 (file)
@@ -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 (file)
index 0000000..56b7989
--- /dev/null
@@ -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 <graphviz/xdot.h>
+
+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).
index 21277be74d0165de629211648d615dfdb3fa3685..0080b8c8410bb5159049d5302f7dfafc8e98860c 100755 (executable)
 *              AT&T Research, Florham Park NJ             *
 **********************************************************/
 
-
 #include <xdot.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <memory.h>
-#include <time.h>
 
-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_pointpts;
+    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)
 {
-    xdotx;
+    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_opop;
-    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)
 {
-    chars;
+    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
index ccdbe4c6811c101c8c89b7466e4bfd076006d560..127d224a18294e0530dd09d90a858a3fde79397e 100755 (executable)
@@ -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*);