]> granicus.if.org Git - graphviz/commitdiff
add lefty, dotty, lneato to graphviz2 tree
authorellson <devnull@localhost>
Thu, 6 Jan 2005 15:01:43 +0000 (15:01 +0000)
committerellson <devnull@localhost>
Thu, 6 Jan 2005 15:01:43 +0000 (15:01 +0000)
cmd/lefty/examples/tree.lefty [new file with mode: 0644]
cmd/lefty/io.h [new file with mode: 0644]
cmd/lefty/lefty.1 [new file with mode: 0644]
cmd/lefty/lefty.c [new file with mode: 0644]
cmd/lefty/lefty.psp [new file with mode: 0644]
cmd/lefty/lex.c [new file with mode: 0644]
cmd/lefty/lex.h [new file with mode: 0644]
cmd/lefty/mem.c [new file with mode: 0644]
cmd/lefty/mem.h [new file with mode: 0644]
cmd/lefty/os/.cvsignore [new file with mode: 0644]
cmd/lefty/os/Makefile.am [new file with mode: 0644]

diff --git a/cmd/lefty/examples/tree.lefty b/cmd/lefty/examples/tree.lefty
new file mode 100644 (file)
index 0000000..92c2997
--- /dev/null
@@ -0,0 +1,195 @@
+load ('def.lefty');
+definit ();
+#
+# initialize window data
+#
+canvas = defcanvas;
+wrect = [0 = ['x' = -5; 'y' = 0;]; 1 = ['x' = 410; 'y' = 500;];];
+setwidgetattr (canvas, ['window' = wrect;]);
+#
+# data structures
+#
+nodearray = [];
+nodenum = 0;
+dist = ['x' = 40; 'y' = 40;];
+defsize = ['x' = 10; 'y' = 10;];
+fontname = 'fixed';
+fontsize = 18;
+tree = null;
+
+# drawing functions
+#
+boxnode = function (node) {
+    local center;
+    box (canvas, node, node.rect, ['color' = 0; 'fill' = 'on';]);
+    box (canvas, node, node.rect);
+    center = [
+        'x' = (node.rect[0].x + node.rect[1].x) / 2;
+        'y' = (node.rect[0].y + node.rect[1].y) / 2;
+    ];
+    if (node.name)
+        text (canvas, node, center, node.name, fontname, fontsize, 'cc');
+};
+circlenode = function (node) {
+    local center, radius;
+    center = [
+        'x' = (node.rect[0].x + node.rect[1].x) / 2;
+        'y' = (node.rect[0].y + node.rect[1].y) / 2;
+    ];
+    radius = [
+        'x' = center.x - node.rect[0].x;
+        'y' = center.y - node.rect[0].y;
+    ];
+    arc (canvas, node, center, radius, ['color' = 0; 'fill' = 'on';]);
+    arc (canvas, node, center, radius);
+    if (node.name)
+        text (canvas, node, center, node.name, fontname, fontsize, 'cc');
+};
+drawnode = boxnode;
+drawedge = function (node1, node2) {
+    line (canvas, null,
+            [
+                'x' = (node1.rect[1].x + node1.rect[0].x) / 2;
+                'y' = node1.rect[0].y;
+            ], [
+                'x' = (node2.rect[1].x + node2.rect[0].x) / 2;
+                'y' = node2.rect[1].y;
+            ]);
+};
+drawtree = function (node) {
+    local i;
+    for (i in nodearray)
+        drawnode (nodearray[i]);
+    drawtreerec (node);
+};
+drawtreerec = function (node) {
+    local i, n;
+    if ((n = tablesize (node.ch)) > 0) {
+        for (i = 0; i < n; i = i + 1) {
+            drawedge (node, node.ch[i]);
+            drawtreerec (node.ch[i]);
+        }
+    }
+};
+redraw = function (c) {
+    if (tree)
+        drawtree (tree);
+};
+
+# layout functions
+#
+complayout = function () {
+    leafx = 0;
+    leafrank = 0;
+    dolayout (tree, wrect[1].y - 10);
+    remove ('leafx');
+    remove ('leafrank');
+};
+dolayout = function (node, pary) {
+    local r, n, i, size, lchp, rchp;
+    size = nodesize (node);
+    if (node.chn > 0) {
+        for (i = 0; i < node.chn; i = i + 1)
+            dolayout (node.ch[i], pary - size.y - dist.y);
+        node.rank = (node.ch[0].rank + node.ch[node.chn - 1].rank) / 2;
+        lchp = node.ch[0].rect;
+        rchp = node.ch[node.chn - 1].rect;
+        r[0].x = lchp[0].x + ((rchp[1].x - lchp[0].x) - size.x) / 2;
+        r[0].y = pary - size.y;
+        r[1].x = r[0].x + size.x;
+        r[1].y = pary;
+        node.rect = r;
+    } else {
+        node.rank = leafrank;
+        r[0].x = leafx;
+        r[0].y = pary - size.y;
+        r[1].x = r[0].x + size.x;
+        r[1].y = pary;
+        leafrank = leafrank + 1;
+        leafx = r[1].x + dist.x;
+        node.rect = r;
+    }
+};
+
+# editing functions
+#
+inode = function (point, name) {
+    local i, nnum, size;
+    nnum = nodenum;
+    if (~name)
+        name = ask ('give name of node:');
+    nodearray[nnum].ch = [];
+    nodearray[nnum].chn = 0;
+    nodearray[nnum].name = name;
+    size = nodesize (nodearray[nnum]);
+    nodearray[nnum].rect[0] = point;
+    nodearray[nnum].rect[1] = ['x' = point.x + size.x; 'y' = point.y + size.y;];
+    nodenum = nodenum + 1;
+    if (~tree) {
+        tree = nodearray[nnum];
+        tree.depth = 0;
+        complayout ();
+        drawtree (tree);
+    } else
+        drawtree (nodearray[nnum]);
+    return nodearray[nnum];
+};
+iedge = function (node1, node2) {
+     node1.ch[node1.chn] = node2;
+     node1.chn = node1.chn + 1;
+     node2.depth = node1.depth + 1;
+     complayout ();
+     clear (canvas);
+     drawtree (tree);
+};
+fix = function (node, op, np) {
+    if (node.depth ~= 0)
+        dist.y = dist.y + (op.y - np.y) / node.depth;
+    if (node.rank ~= 0)
+        dist.x = dist.x + (np.x - op.x) / node.rank;
+    complayout ();
+    clear (canvas);
+    drawtree (tree);
+};
+nodesize = function (node) {
+    local siz;
+    if (~(siz = textsize (canvas, node.name, fontname, fontsize)))
+        siz = defsize;
+    else {
+        siz.x = siz.x + 8;
+        siz.y = siz.y + 8;
+    }
+    return siz;
+};
+changenode = function (nodestyle) {
+    drawnode = nodestyle;
+    clear (canvas);
+    drawtree (tree);
+};
+
+# user interface functions
+#
+leftdown = function (data) {
+    if (~data.obj)
+        inode (data.pos, null);
+};
+leftup = function (data) {
+    if (data.pobj)
+        fix (data.pobj, data.ppos, data.pos);
+};
+middleup = function (data) {
+    if (data.pobj & data.obj)
+        iedge (data.pobj, data.obj);
+};
+dops = function () {
+    local s;
+
+    s = ['x' = 8 * 300; 'y' = 10.5 * 300;];
+    fontname = 'Times-Roman';
+    canvas = createwidget (-1, ['type' = 'ps'; 'size' = s;]);
+    setwidgetattr (canvas, ['window' = wrect;]);
+    drawtree (tree);
+    destroywidget (canvas);
+    canvas=defcanvas;
+    fontname = 'fixed';
+};
diff --git a/cmd/lefty/io.h b/cmd/lefty/io.h
new file mode 100644 (file)
index 0000000..cc940f3
--- /dev/null
@@ -0,0 +1,81 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Lefteris Koutsofios - AT&T Bell Laboratories */
+
+#ifndef _IO_H
+#define _IO_H
+
+    typedef enum {
+       IO_FILE, IO_PTY, IO_PIPE, IO_SOCKET,
+#ifdef FEATURE_CS
+       IO_CS,
+#endif
+       IO_SIZE
+    } iotype_t;
+
+    typedef struct io_t {
+       int inuse, ismonitored;
+       iotype_t type;
+       FILE *ifp, *ofp;
+       int pid;
+       char *buf;
+    } io_t;
+
+#ifdef FEATURE_MS
+#define IOmonitor(ioi, set) do { \
+    iop[ioi].ismonitored = TRUE; \
+} while (0)
+#define IOunmonitor(ioi, set) do { \
+    iop[ioi].ismonitored = FALSE; \
+} while (0)
+#else
+#define IOmonitor(ioi, set) do { \
+    iop[ioi].ismonitored = TRUE; \
+    FD_SET (fileno (iop[ioi].ifp), &set); \
+} while (0)
+#define IOunmonitor(ioi, set) do { \
+    iop[ioi].ismonitored = FALSE; \
+    FD_CLR (fileno (iop[ioi].ifp), &set); \
+} while (0)
+#endif
+
+#define IOismonitored(ioi) (iop[ioi].ismonitored == TRUE)
+#define IOINCR 5
+#define IOSIZE sizeof (io_t)
+#define IOBUFSIZE 2048
+
+    extern io_t *iop;
+    extern int ion;
+
+    void IOinit(void);
+    void IOterm(void);
+    int IOopen(char *, char *, char *, char *);
+    int IOclose(int, char *);
+    int IOreadline(int, char *, int);
+    int IOread(int, char *, int);
+    int IOwriteline(int, char *);
+
+#endif                         /* _IO_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cmd/lefty/lefty.1 b/cmd/lefty/lefty.1
new file mode 100644 (file)
index 0000000..bf73d04
--- /dev/null
@@ -0,0 +1,120 @@
+.TH LEFTY 1
+.SH NAME
+lefty \- A Programmable Graphics Editor
+.SH SYNOPSIS
+.B lefty
+[
+.I options
+] [
+.I file
+]
+.SH DESCRIPTION
+.B lefty
+is a two-view graphics editor for technical pictures. This editor has
+no hardwired knowledge about specific picture layouts or editing operations.
+Each picture is described by a program that contains functions to draw the
+picture and functions to perform editing operations that are appropriate for
+the specific picture. Primitive user actions, like mouse and keyboard events,
+are also bound to functions in this program. Besides the graphical view of the
+picture itself, the editor presents a textual view of the program that
+describes the picture. Programmability and the two-view interface allow the
+editor to handle a variety of pictures, but are particularly useful for
+pictures used in technical contexts, e.g., graphs and trees. Also,
+.B lefty
+can communicate with other processes. This feature allows it to use existing
+tools to compute specific picture layouts and allows external processes to use
+the editor as a front end to display their data structures graphically.
+.SH USAGE
+The file name is optional. It may be
+.BR - ,
+for reading from standard input.
+.B lefty
+uses two environment variables,
+.B LEFTYPATH
+and
+.BR LEFTYOPTIONS .
+.B LEFTYPATH
+is a colon separated list of directories. When
+.B lefty
+tries to open a file, it searches that path for the file. When
+.B lefty
+tries to start up another process, it searches
+.B LEFTYPATH
+first, then the standard
+.B PATH
+variable.
+.B LEFTYOPTIONS
+can be used to set specific options. Options specified on the command line
+override options set through this variable.
+.SH OPTIONS
+.TP
+.B -x
+Instructs the editor to exit after processing
+.BR file .
+.TP
+.B "-e <expression>"
+.B <expression>
+is parsed and executed.
+.TP
+.B -el <num>
+Set error reporting level. The default value is
+.BR 0 .
+.B 0
+never prints any messages.
+.B 1
+prints severe errors, such as trying to return from a non function.
+.B 2
+is the most useful: it reports function calls that cannot be executed, either
+because there is no function, or because of argument mismatches.
+.B 3
+also warns about bad variable names.
+.B 4,5
+warn about expressions that do not return a value. Only level
+.B 1
+messages are real errors. The rest arise from legal
+.B lefty
+statements, but may be cased by some logic errors.
+.TP
+.B "-sd <num>"
+Specifies how much of the stack to show, when an error message is to be
+printed. The defualt value is
+.BR 2 .
+With
+.BR 0 ,
+no part of the stack is shown. With
+.BR 1 ,
+only the top stack frame is printed. With
+.BR 2 ,
+the full stack is printed.
+.TP
+.B "-sb <num>"
+Specifies how much of each function in the stack to show, when an error message
+is to be printed. The default value is
+.BR 2 .
+With
+.BR 0 ,
+no part of the function is shown. With
+.BR 1 ,
+only the line around the error is printed. With
+.BR 2 ,
+the full function body is printed.
+.TP
+.B "-df <string>"
+Sets the default font. This font is used whenever a requested font cannot be
+found. The string must be a legal X font. If string is
+.BR "''" ,
+.B lefty
+will draw small boxes instead of text.
+.TP
+.B "-ps <file>"
+Specifies a default file name for postscript files. This name is used when no
+name is specified in the
+.B createwidget
+call. The default file name is
+.BR out.ps .
+.TP
+.B -V
+Prints the version.
+.SH SEE ALSO
+.I lefty
+user guide.
diff --git a/cmd/lefty/lefty.c b/cmd/lefty/lefty.c
new file mode 100644 (file)
index 0000000..51432f2
--- /dev/null
@@ -0,0 +1,534 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+
+/* Lefteris Koutsofios - AT&T Bell Laboratories */
+
+#ifdef FEATURE_GTK
+#include <gtk/gtk.h>
+#include <glib/gmain.h>
+#endif
+
+#include "common.h"
+#include "g.h"
+#include "code.h"
+#include "io.h"
+#include "mem.h"
+#include "tbl.h"
+#include "parse.h"
+#include "exec.h"
+#include "str.h"
+#include "display.h"
+#include "internal.h"
+#include "txtview.h"
+#include "gfxview.h"
+#ifdef FEATURE_GMAP
+#include "gmap.h"
+#include "gmap2l.h"
+#endif
+#ifndef FEATURE_MS
+#include <sys/time.h>
+#ifdef HAVE_UNISTD_H
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#ifdef STATS
+#include <sys/resource.h>
+#endif
+#endif
+
+/* the gnu way is to test for features explicitly */
+#ifdef HAVE_FILE_R
+#define canread(fp) ((fp)->_r > 0)
+#else
+#ifdef HAVE_FILE_IO_READ_END
+#define canread(fp) ((fp)->_IO_read_end > (fp)->_IO_read_ptr)
+#else
+#ifdef HAVE_FILE_CNT
+#define canread(fp) ((fp)->_cnt > 0)
+#else
+#ifdef HAVE_FILE_NEXT
+#define canread(fp) ((fp)->next < (fp)->endb)
+#else
+#ifdef HAVE___FREADABLE
+#define canread(fp) (__freadable(fp))
+
+/* the other way is to presume a feature based on OS */
+#else
+#ifdef FEATURE_CS
+#define canread(fp) ((fp)->next < (fp)->endb)
+#else
+#ifdef FEATURE_GNU
+#define canread(fp) ((fp)->_IO_read_end > (fp)->_IO_read_ptr)
+#else
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__Mac_OSX__)
+#define canread(fp) ((fp)->_r > 0)
+#endif
+#endif
+#endif
+#endif
+
+#endif
+#endif
+#endif
+#endif
+
+#ifdef FEATURE_GMAP
+static int gmapon;
+#endif
+
+static Grect_t txtcoords = {
+    {1, 1}, {449, 599},
+};
+
+#ifdef STATS
+static time_t stime;
+#endif
+
+static int endflag = FALSE;
+
+static char *exprstr;
+static FILE *fp;
+
+static int processinput(int);
+static void processargs(int, char **);
+static void processstr(char *);
+static void printusage(void);
+
+#if defined(FEATURE_X11) || defined(FEATURE_NONE) || defined(FEATURE_GTK)
+
+int main(int argc, char **argv)
+{
+    Tobj co;
+    Psrc_t src;
+
+#ifdef MTRACE
+    extern int Mt_certify;
+    Mt_certify = 1;
+#endif
+#ifdef STATS
+    stime = time(NULL);
+#endif
+
+    idlerunmode = 0;
+    exprstr = NULL;
+    fp = NULL;
+    init(argv[0]);
+    Minit(GFXprune);
+    Ginit();
+    FD_SET(Gxfd, &inputfds);
+
+    Eerrlevel = 1;
+    Estackdepth = 2;
+    Eshowbody = 1;
+    Eshowcalls = 1;
+
+    processstr(leftyoptions);
+    argv++, argc--;
+    processargs(argc, argv);
+
+    if (setjmp(exitljbuf))
+       goto eop;
+
+    Cinit();
+    IOinit();
+    Tinit();
+    Pinit();
+    Einit();
+    Sinit();
+    Dinit();
+    Iinit();
+    TXTinit(txtcoords);
+    GFXinit();
+#ifdef FEATURE_GMAP
+    gmapon = TRUE, G2Linit();
+#endif
+
+    if (exprstr) {
+       src.flag = CHARSRC, src.s = exprstr, src.fp = NULL;
+       src.tok = -1, src.lnum = 1;
+       while ((co = Punit(&src)))
+           Eunit(co);
+    }
+    if (fp) {
+       src.flag = FILESRC, src.s = NULL, src.fp = fp;
+       src.tok = -1, src.lnum = 1;
+       while ((co = Punit(&src)))
+           Eunit(co);
+    }
+    if (endflag)
+       goto eop;
+
+    TXTupdate();
+
+
+#ifdef FEATURE_GTK
+    while (gtk_events_pending()) {
+       gtk_main_iteration();
+    }
+
+    Gneedredraw = FALSE;
+    while (TRUE) {
+       if (gtk_events_pending()) {
+           GdkEvent *eve;
+
+           gtk_main_iteration();
+           if (Gneedredraw)
+               GFXredraw(), Gneedredraw = FALSE;
+           if (Gbuttonsdown > 0) {
+               GFXmove(), Gprocessevents(FALSE, G_ONEEVENT);
+               processinput(FALSE);
+           } else {
+               if (Mcouldgc) {
+                   if (!processinput(FALSE))
+                       Mdogc(M_GCINCR);
+               } else if (idlerunmode) {
+                   if (!processinput(FALSE))
+                       GFXidle();
+               } else
+                   processinput(TRUE);
+           }
+#ifdef FEATURE_GMAP
+           if (gmapon)
+               GMAPupdate();
+#endif
+           if (Erun)
+               TXTupdate(), Erun = FALSE;
+       }
+    }
+#else
+
+    Gneedredraw = FALSE;
+    for (;;) {
+       if (Gneedredraw)
+           GFXredraw(), Gneedredraw = FALSE;
+       if (Gbuttonsdown > 0) {
+           GFXmove(), Gprocessevents(FALSE, G_ONEEVENT);
+           processinput(FALSE);
+       } else {
+           if (Mcouldgc) {
+               if (!processinput(FALSE))
+                   Mdogc(M_GCINCR);
+           }
+           if (idlerunmode) {
+               if (!processinput(FALSE))
+                   GFXidle();
+           } else
+               processinput(TRUE);
+       }
+#ifdef FEATURE_GMAP
+       if (gmapon)
+           GMAPupdate();
+#endif
+       if (Erun)
+           TXTupdate(), Erun = FALSE;
+    }
+#endif                         /* end of else part of FEATURE_GTK */
+
+  eop:
+#ifdef PARANOID
+#ifdef FEATURE_GMAP
+    if (gmapon)
+       G2Lterm();
+#endif
+    GFXterm();
+    TXTterm();
+    Iterm();
+    Dterm();
+    Sterm();
+    Eterm();
+    Pterm();
+    Tterm();
+    IOterm();
+    Cterm();
+    Gterm();
+    Mterm();
+    FD_CLR(Gxfd, &inputfds);
+    term();
+#endif
+    printusage();
+    return 0;
+}
+
+#else
+
+extern char **__argv;
+extern int __argc;
+
+HANDLE hinstance, hprevinstance;
+
+int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
+                  LPSTR lpCmdLine, int nCmdShow)
+{
+    Tobj co;
+    Psrc_t src;
+
+    hinstance = hInstance;
+    hprevinstance = hPrevInstance;
+    idlerunmode = 0;
+    exprstr = NULL;
+    fp = NULL;
+    init(NULL);
+    Ginit();
+#ifndef FEATURE_MS
+    FD_SET(Gxfd, &inputfds);
+#endif
+
+    Eerrlevel = 1;
+    Estackdepth = 2;
+    Eshowbody = 1;
+    Eshowcalls = 1;
+
+    processstr(leftyoptions);
+    __argv++, __argc--;
+    processargs(__argc, __argv);
+
+    if (setjmp(exitljbuf))
+       goto eop;
+
+    Cinit();
+    IOinit();
+    Minit(GFXprune);
+    Tinit();
+    Pinit();
+    Einit();
+    Sinit();
+    Dinit();
+    Iinit();
+    TXTinit(txtcoords);
+    GFXinit();
+
+    if (exprstr) {
+       src.flag = CHARSRC, src.s = exprstr, src.fp = NULL;
+       src.tok = -1, src.lnum = 1;
+       while ((co = Punit(&src)))
+           Eunit(co);
+    }
+    if (fp) {
+       src.flag = FILESRC, src.s = NULL, src.fp = fp;
+       src.tok = -1, src.lnum = 1;
+       while ((co = Punit(&src)))
+           Eunit(co);
+    }
+    if (endflag)
+       goto eop;
+
+    TXTupdate();
+
+    Gneedredraw = FALSE;
+    for (;;) {
+       if (Gneedredraw)
+           GFXredraw(), Gneedredraw = FALSE;
+       if (Gbuttonsdown > 0)
+           GFXmove(), Gprocessevents(FALSE, G_ONEEVENT);
+       else {
+           if (Mcouldgc) {
+               if (!processinput(FALSE))
+                   Mdogc(M_GCINCR);
+           } else if (idlerunmode) {
+               if (!processinput(FALSE))
+                   GFXidle();
+           } else
+               processinput(TRUE);
+       }
+       if (Erun)
+           TXTupdate(), Erun = FALSE;
+    }
+
+  eop:
+#ifdef PARANOID
+    GFXterm();
+    TXTterm();
+    Iterm();
+    Dterm();
+    Sterm();
+    Eterm();
+    Pterm();
+    Tterm();
+    Mterm();
+    IOterm();
+    Cterm();
+    Gterm();
+    term();
+#endif
+    printusage();
+    exit(0);
+}
+
+#endif
+
+#ifndef FEATURE_MS
+static struct timeval longwait = { 1000, 0 };
+static struct timeval zerowait = { 0, 0 };
+#endif
+
+static int processinput(int waitflag)
+{
+    fd_set fdset;
+#ifndef FEATURE_MS
+    struct timeval tz, *tzp;
+#else
+    HANDLE evs[MAXIMUM_WAIT_OBJECTS];
+    int evn;
+#endif
+    int n, rtn;
+    int ioi;
+
+    rtn = 0;
+    while (Gprocessevents(FALSE, G_MANYEVENTS))
+       rtn = 1;
+#ifndef FEATURE_MS
+    for (ioi = 0, n = 0; ioi < ion; ioi++)
+       if (iop[ioi].inuse && iop[ioi].ismonitored &&
+           FD_ISSET(fileno(iop[ioi].ifp), &inputfds) &&
+           canread(iop[ioi].ifp))
+           GFXmonitorfile(ioi), n++;
+    if (n || rtn)
+       return 1;
+    if (Gneedredraw)
+       return 0;
+    tz = (waitflag && !rtn) ? longwait : zerowait;
+    tzp = &tz;
+    fdset = inputfds;
+    if ((n = select(FD_SETSIZE, &fdset, NULL, NULL, tzp)) <= 0)
+       return rtn;
+    rtn = 1;
+    if (FD_ISSET(Gxfd, &fdset))
+       Gprocessevents(TRUE, G_MANYEVENTS), n--;
+    if (!n)
+       return rtn;
+    Gsync();
+    for (ioi = 0; n > 0 && ioi < ion; ioi++)
+       if (iop[ioi].inuse && iop[ioi].ismonitored &&
+           FD_ISSET(fileno(iop[ioi].ifp), &fdset))
+           GFXmonitorfile(ioi), n--;
+#else
+    for (ioi = 0, n = 0, evn = 0; ioi < ion; ioi++) {
+       if (!iop[ioi].inuse || !IOismonitored(ioi, inputfds))
+           continue;
+       if ((iop[ioi].type == IO_FILE && canread(iop[ioi].ifp)) ||
+           (iop[ioi].type == IO_PIPE && iop[ioi].buf[0]))
+           GFXmonitorfile(ioi), n++;
+       if (iop[ioi].type != IO_PIPE)
+           continue;
+       evs[evn++] = iop[ioi].ifp;
+    }
+    if (n)
+       return 1;
+    if (Gneedredraw)
+       return 0;
+    n = MsgWaitForMultipleObjects(evn, evs, FALSE,
+                                 (waitflag && !rtn) ? 1 : 0, QS_ALLINPUT);
+    if (n == WAIT_TIMEOUT || n < WAIT_OBJECT_0 || n > WAIT_OBJECT_0 + evn)
+       return rtn;
+    if (n == WAIT_OBJECT_0 + evn)
+       Gprocessevents(TRUE, G_MANYEVENTS);
+    Gsync();
+    for (ioi = 0; ioi < ion; ioi++)
+       if (iop[ioi].inuse && IOismonitored(ioi) &&
+           (iop[ioi].type == IO_FILE || (iop[ioi].type == IO_PIPE &&
+                                         evs[n - WAIT_OBJECT_0] ==
+                                         iop[ioi].ifp)))
+           GFXmonitorfile(ioi);
+#endif
+    return rtn;
+}
+
+static void processstr(char *buf)
+{
+    char *words[100];
+    char *s, *s1;
+    int i;
+
+    if (!(s = buf) || *s == 0)
+       return;
+    s = strdup(s);
+    for (i = 0, s1 = s; *s1;) {
+       for (; *s1 && *s1 == ' '; s1++);
+       if (!*s1)
+           break;
+       words[i++] = s1;
+       for (; *s1 && *s1 != ' '; s1++);
+       if (*s1)
+           *s1 = '\000', s1++;
+    }
+    words[i] = NULL;
+    processargs(i, words);
+    free(s);
+}
+
+static void processargs(int argc, char *argv[])
+{
+    while (argc) {
+       if (Strcmp(argv[0], "-x") == 0)
+           endflag = TRUE;
+       else if (Strcmp(argv[0], "-e") == 0)
+           exprstr = argv[1], argv++, argc--;
+       else if (Strcmp(argv[0], "-el") == 0)
+           Eerrlevel = atoi(argv[1]), argv++, argc--;
+       else if (Strcmp(argv[0], "-sd") == 0)
+           Estackdepth = atoi(argv[1]), argv++, argc--;
+       else if (Strcmp(argv[0], "-sb") == 0)
+           Eshowbody = atoi(argv[1]), argv++, argc--;
+       else if (Strcmp(argv[0], "-sc") == 0)
+           Eshowcalls = atoi(argv[1]), argv++, argc--;
+       else if (Strcmp(argv[0], "-df") == 0)
+           Gdefaultfont = argv[1], argv++, argc--;
+       else if (Strcmp(argv[0], "-w") == 0)
+           warnflag = TRUE;
+       else if (Strcmp(argv[0], "-ps") == 0)
+           Gpscanvasname = argv[1], argv++, argc--;
+       else if (Strcmp(argv[0], "-V") == 0)
+           fprintf(stderr, "lefty version %s (%s)\n", VERSION, BUILDDATE);
+       else if (Strcmp(argv[0], "-") == 0)
+           fp = stdin;
+       else {
+           if ((fp = fopen(argv[0], "r")) == NULL)
+               panic(POS, "main", "cannot open input file: %s", argv[0]);
+       }
+       argv++, argc--;
+    }
+    if (Eerrlevel > 1)
+       Gerrflag = TRUE;
+}
+
+static void printusage(void)
+{
+#ifdef STATS
+    struct rusage ru;
+
+    getrusage(RUSAGE_SELF, &ru);
+    Mreport();
+#ifdef FEATURE_RUSAGE
+    printf("user   time %13.3lf\n",
+          ru.ru_utime.tv_sec + ru.ru_utime.tv_nsec / 1000000000.0);
+    printf("system time %13.3lf\n",
+          ru.ru_stime.tv_sec + ru.ru_stime.tv_nsec / 1000000000.0);
+#else
+    printf("user   time %13.3lf\n",
+          ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000.0);
+    printf("system time %13.3lf\n",
+          ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1000000.0);
+#endif
+    printf("resident size  %10d\n", ru.ru_maxrss * getpagesize());
+    printf("input            %8d\n", ru.ru_inblock);
+    printf("output           %8d\n", ru.ru_oublock);
+    printf("socket msgs sent %8d\n", ru.ru_msgsnd);
+    printf("socket msgs rcvd %8d\n", ru.ru_msgrcv);
+    printf("real time        %8d\n", time(NULL) - stime);
+    fflush(stdout);
+#endif
+}
diff --git a/cmd/lefty/lefty.psp b/cmd/lefty/lefty.psp
new file mode 100644 (file)
index 0000000..c3c9b01
--- /dev/null
@@ -0,0 +1,79 @@
+/BOX {
+    /boxy1 exch def /boxx1 exch def /boxy0 exch def /boxx0 exch def
+    boxx0 boxy0 moveto boxx1 boxy0 lineto
+    boxx1 boxy1 lineto boxx0 boxy1 lineto
+    closepath
+} def
+/SCP { stroke initclip newpath BOX clip newpath } def
+/CL { stroke setrgbcolor } def
+/DO { stroke } def
+/NP { newpath } def
+/FI { fill } def
+/LI { moveto lineto } def
+/CT { curveto } def
+/AR {
+    /ang2 exch def /ang1 exch def
+    /radius exch def /y2x exch def /cy exch def /cx exch def
+    gsave
+        cx cy translate 1 y2x scale 0 0 radius ang1 ang2 arc stroke
+    grestore
+} def
+/ARF {
+    /ang2 exch def /ang1 exch def
+    /radius exch def /y2x exch def /cy exch def /cx exch def
+    gsave
+        cx cy translate 1 y2x scale 0 0 radius ang1 ang2 arc fill
+    grestore
+} def
+/TXT {
+    /texth exch def
+    /textf exch def
+    /textn exch def
+    /texts exch def
+    /textyj exch def /texty exch def
+    /textxj exch def /textx exch def
+    textf findfont texth scalefont dup setfont
+    /FontBBox get 1 get 1000 div texth mul /textbl exch def
+    /textth texth textn mul def /texttw 0 def
+    0 1 textn 1 sub {
+        texts exch get 0 get stringwidth pop
+        dup texttw gt { /texttw exch def } { pop } ifelse
+    } for
+    textyj (d) eq { /ty texty textth add def } if
+    textyj (c) eq { /ty texty textth 2 div add def } if
+    textyj (u) eq { /ty texty def } if
+    /ty ty textbl sub def
+    textxj (l) eq { /tx textx def } if
+    textxj (c) eq { /tx textx texttw 2 div sub def } if
+    textxj (r) eq { /tx textx texttw sub def } if
+    0 1 textn 1 sub {
+        /ty ty texth sub def
+        texts exch get dup 0 get /ts exch def 1 get /tj exch def
+        tj (l) eq { tx ty moveto ts show } if
+        tj (n) eq {
+            tx texttw ts stringwidth pop sub 2 div add ty moveto ts show
+        } if
+        tj (r) eq {
+            tx texttw ts stringwidth pop sub add ty moveto ts show
+        } if
+    } for
+} def
+
+/colorimage where {
+    pop
+} {
+    /bwproc {
+        rgbproc dup length 3 idiv string 0 3 0 5 -1 roll {
+            add 2 1 roll 1 sub dup 0 eq {
+                pop 3 idiv 3 -1 roll dup 4 -1 roll
+                dup 3 1 roll 5 -1 roll put 1 add 3 0
+            } {
+                2 1 roll
+            } ifelse
+        } forall
+        pop pop pop
+    } def
+    /colorimage {
+        pop pop /rgbproc exch def {bwproc} image
+    } bind def
+} ifelse
diff --git a/cmd/lefty/lex.c b/cmd/lefty/lex.c
new file mode 100644 (file)
index 0000000..31c61a1
--- /dev/null
@@ -0,0 +1,293 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+
+/* Lefteris Koutsofios - AT&T Bell Laboratories */
+
+#include "common.h"
+#include "lex.h"
+
+Ltype_t Ltok;
+char Lstrtok[MAXTOKEN];
+
+Lname_t Lnames[] = {
+    /* L_SEMI     */ ";",
+    /* L_ASSIGN   */ "=",
+    /* L_OR       */ "|",
+    /* L_AND      */ "&",
+    /* L_EQ       */ "==",
+    /* L_NE       */ "~=",
+    /* L_LT       */ "<",
+    /* L_LE       */ "<=",
+    /* L_GT       */ ">",
+    /* L_GE       */ ">=",
+    /* L_PLUS     */ "+",
+    /* L_MINUS    */ "-",
+    /* L_MUL      */ "*",
+    /* L_DIV      */ "/",
+    /* L_MOD      */ "%",
+    /* L_NOT      */ "~",
+    /* L_STRING   */ "STRING",
+    /* L_NUMBER   */ "NUMBER",
+    /* L_ID       */ "IDENTIFIER",
+    /* L_DOT      */ "DOT",
+    /* L_LB       */ "LEFT BRACKET",
+    /* L_RB       */ "RIGHT BRACKET",
+    /* L_FUNCTION */ "FUNCTION",
+    /* L_LP       */ "LEFT PARENTHESIS",
+    /* L_RP       */ "RIGHT PARENTHESIS",
+    /* L_LCB      */ "LEFT CURLY BRACE",
+    /* L_RCB      */ "RIGHT CURLY BRACE",
+    /* L_LOCAL    */ "LOCAL",
+    /* L_COLON    */ ":",
+    /* L_COMMA    */ ",",
+    /* L_IF       */ "IF",
+    /* L_ELSE     */ "ELSE",
+    /* L_WHILE    */ "WHILE",
+    /* L_FOR      */ "FOR",
+    /* L_IN       */ "IN",
+    /* L_BREAK    */ "BREAK",
+    /* L_CONTINUE */ "CONTINUE",
+    /* L_RETURN   */ "RETURN",
+    /* L_INTERNAL */ "INTERNAL",
+    /* L_EOF      */ "EOF"
+};
+
+static char *unitp, *ucp;
+static FILE *lfp;
+static int lsrc, seeneof, linenum;
+
+#define MAXBUF 10000
+static char unitbuf[MAXBUF];
+
+/* keyword mapping */
+static struct keyword {
+    char *str;
+    int tok;
+} keywords[] = {
+    {
+    "function", L_FUNCTION}, {
+    "local", L_LOCAL}, {
+    "if", L_IF}, {
+    "else", L_ELSE}, {
+    "while", L_WHILE}, {
+    "for", L_FOR}, {
+    "in", L_IN}, {
+    "break", L_BREAK}, {
+    "continue", L_CONTINUE}, {
+    "return", L_RETURN}, {
+    "internal", L_INTERNAL}, {
+    NULL, 0}
+};
+
+/* single character token mapping */
+static struct keychar {
+    int chr, tok;
+} keychars[] = {
+    {
+    ';', L_SEMI}, {
+    '|', L_OR}, {
+    '&', L_AND}, {
+    '+', L_PLUS}, {
+    '-', L_MINUS}, {
+    '*', L_MUL}, {
+    '/', L_DIV}, {
+    '%', L_MOD}, {
+    '.', L_DOT}, {
+    '[', L_LB}, {
+    ']', L_RB}, {
+    '(', L_LP}, {
+    ')', L_RP}, {
+    '{', L_LCB}, {
+    '}', L_RCB}, {
+    ':', L_COLON}, {
+    ',', L_COMMA}, {
+    '\000', 0}
+};
+
+static Ltype_t gtok(void);
+static int sgetc(void);
+static void sungetc(void);
+
+void Lsetsrc(int src, char *s, FILE * fp, int tok, int lnum)
+{
+    if (src == CHARSRC)
+       unitp = ucp = s;
+    else if (src == FILESRC)
+       unitp = ucp = unitbuf, unitbuf[0] = '\000', lfp = fp;
+    lsrc = src;
+    linenum = lnum;
+    seeneof = FALSE;
+    if (tok == -1 || tok == L_EOF)
+       Ltok = gtok();
+    else
+       Ltok = (Ltype_t) tok;
+}
+
+void Lgetsrc(int *srcp, char **sp, FILE ** fpp, int *tokp, int *lnump)
+{
+    *srcp = lsrc;
+    *sp = ucp;
+    *fpp = lfp;
+    *tokp = Ltok;
+    if (*ucp && *ucp == '\n')
+       linenum++;
+    *lnump = linenum;
+}
+
+void Lprintpos(void)
+{
+    char *s1, *s2;
+    char c;
+
+    printf("at line %d: ", linenum);
+    for (s1 = ucp; s1 > unitp && *s1 != '\n'; s1--);
+    for (s2 = ucp; *s2 && *s2 != '\n'; s2++);
+    c = *s2, *s2 = '\000';
+    printf("%s\n", s1);
+    *s2 = c;
+}
+
+void Lgtok(void)
+{
+    Ltok = gtok();
+}
+
+static Ltype_t gtok(void)
+{
+    struct keyword *kwp;
+    struct keychar *kcp;
+    int c, qc, nc;
+    char *p;
+
+    while ((c = sgetc()) != EOF) {
+       if (c == '#')
+           while ((c = sgetc()) != '\n');
+       if (c != ' ' && c != '\t' && c != '\n')
+           break;
+    }
+    if (c == EOF)
+       return L_EOF;
+    /* check for keywords and identifiers */
+    if (isalpha(c) || c == '_') {
+       p = &Lstrtok[0], *p++ = c;
+       while (isalpha((c = sgetc())) || isdigit(c) || c == '_')
+           *p++ = c;
+       sungetc();
+       *p = '\000';
+       for (kwp = &keywords[0]; kwp->str; kwp++)
+           if (Strcmp(kwp->str, Lstrtok) == 0)
+               return (Ltype_t) (kwp->tok);
+       return L_ID;
+    }
+    /* check for number constant */
+    if (isdigit(c)) {
+       p = &Lstrtok[0], *p++ = c;
+       while (isdigit((c = sgetc())))
+           *p++ = c;
+       if (c == '.') {
+           *p++ = c;
+           while (isdigit((c = sgetc())))
+               *p++ = c;
+       }
+       sungetc();
+       *p = '\000';
+       return L_NUMBER;
+    }
+    /* check for string constants */
+    if (c == '"' || c == '\'') {
+       p = &Lstrtok[0];
+       qc = c;
+       while ((c = sgetc()) != EOF && c != qc)
+           *p++ = c;           /* FIXME: deal with \'s */
+       if (c == EOF)
+           return L_EOF;
+       *p = '\000';
+       return L_STRING;
+    }
+    /* check for single letter keywords */
+    for (kcp = &keychars[0]; kcp->chr; kcp++)
+       if (kcp->chr == c)
+           return (Ltype_t) (kcp->tok);
+    /* check for 2/1 letter keywords */
+    if (c == '=' || c == '~' || c == '<' || c == '>') {
+       nc = sgetc();
+       if (nc == '=') {
+           switch (c) {
+           case '=':
+               return L_EQ;
+           case '~':
+               return L_NE;
+           case '<':
+               return L_LE;
+           case '>':
+               return L_GE;
+           }
+       } else {
+           sungetc();
+           switch (c) {
+           case '=':
+               return L_ASSIGN;
+           case '~':
+               return L_NOT;
+           case '<':
+               return L_LT;
+           case '>':
+               return L_GT;
+           }
+       }
+    }
+    return L_EOF;
+}
+
+static int sgetc(void)
+{
+    if (seeneof)
+       return EOF;
+    if (*ucp == '\000') {
+       if (lsrc == CHARSRC) {
+           seeneof = TRUE;
+           linenum++;
+           return EOF;
+       } else if (lsrc == FILESRC) {
+           if (ucp != unitp)
+               *unitp = *(ucp - 1), ucp = unitp + 1;
+           else
+               ucp = unitp;
+           *ucp = '\000';
+           if (!fgets(ucp, MAXBUF - (ucp - unitp), lfp)) {
+               seeneof = TRUE;
+               return EOF;
+           }
+       }
+    }
+    if (*ucp == '\n')
+       linenum++;
+    return *ucp++;
+}
+
+static void sungetc(void)
+{
+    if (seeneof) {
+       seeneof = FALSE;
+       return;
+    }
+    if (ucp == unitp)
+       panic(POS, "sungetc", "unget before start of string");
+    ucp--;
+    if (*ucp == '\n')
+       linenum--;
+}
diff --git a/cmd/lefty/lex.h b/cmd/lefty/lex.h
new file mode 100644 (file)
index 0000000..d5e6a72
--- /dev/null
@@ -0,0 +1,51 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Lefteris Koutsofios - AT&T Bell Laboratories */
+
+#ifndef _LEX_H
+#define _LEX_H
+    typedef enum {
+       L_SEMI, L_ASSIGN, L_OR, L_AND, L_EQ, L_NE, L_LT, L_LE, L_GT, L_GE,
+           L_PLUS,
+       L_MINUS, L_MUL, L_DIV, L_MOD, L_NOT, L_STRING, L_NUMBER, L_ID,
+           L_DOT,
+       L_LB, L_RB, L_FUNCTION, L_LP, L_RP, L_LCB, L_RCB, L_LOCAL, L_COLON,
+       L_COMMA, L_IF, L_ELSE, L_WHILE, L_FOR, L_IN, L_BREAK, L_CONTINUE,
+       L_RETURN, L_INTERNAL, L_EOF, L_SIZE
+    } Ltype_t;
+
+#define MAXTOKEN 1000
+    typedef char *Lname_t;
+
+    extern Ltype_t Ltok;
+    extern char Lstrtok[];
+    extern Lname_t Lnames[];
+
+    void Lsetsrc(int, char *, FILE *, int, int);
+    void Lgetsrc(int *, char **, FILE **, int *, int *);
+    void Lprintpos(void);
+    void Lgtok(void);
+#endif                         /* _LEX_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cmd/lefty/mem.c b/cmd/lefty/mem.c
new file mode 100644 (file)
index 0000000..de66eac
--- /dev/null
@@ -0,0 +1,426 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+
+/* Lefteris Koutsofios - AT&T Bell Laboratories */
+
+#include "common.h"
+#include "mem.h"
+
+/* SHORTCUT: the following are imported from tbl.c */
+extern void Tgchelper(void *), Tfreehelper(void *);
+
+#define M_MAXTYPES 6
+
+int Mhaspointers[M_MAXTYPES];
+Mgcstate_t Mgcstate;
+int Mcouldgc;
+
+typedef struct buffer_t {
+    void *data;
+    struct buffer_t *next;
+} buffer_t;
+#define BUFFERSIZE sizeof (buffer_t)
+static buffer_t *bufferlist;
+
+typedef struct freeobj_t {
+    Mheader_t head;
+    void *next;
+} freeobj_t;
+#define FREEOBJSIZE sizeof (freeobj_t)
+#define FREESIZE sizeof (void *)
+static void **freearray;
+static long freen;
+
+#define MARKSIZE sizeof (void *)
+#define MARKINCR 100
+static void **markarray;
+static long markn, marki;
+
+#define OTSIZE sizeof (void *)
+#define OTINCR 1000
+static void **otarray[2];
+static long otn, oti, otj;
+static char otarea[2];
+
+static void (*cbfunc) (void);
+
+#define GCINCRSTEPS 4
+static int gcsteps = GCINCRSTEPS;
+
+#define NUMOFALLOCS 10
+static int numofallocs = 0;
+
+#define CALCNUM(size) ((size < 20) ? 1000 : ((size < 200) ? 100 : 1))
+
+#ifdef STATS
+static caddr_t origsbrk, finsbrk;
+static long objnum, objsiz;
+static long typenum[M_MAXTYPES], typesiz[M_MAXTYPES];
+#endif
+
+static void allocbuffer(long);
+
+void Minit(void (*func) (void))
+{
+
+#ifdef STATS
+    int i;
+
+    origsbrk = (caddr_t) sbrk(0);
+    for (i = 0; i < M_MAXTYPES; i++)
+       typenum[i] = typesiz[i] = 0;
+#endif
+
+    freearray = Marrayalloc((long) FREESIZE);
+    freen = 1;
+    freearray[0] = NULL;
+    markarray = Marrayalloc((long) MARKINCR * MARKSIZE);
+    markn = MARKINCR;
+    marki = 0;
+    otarray[0] = Marrayalloc((long) OTINCR * OTSIZE);
+    otarray[1] = Marrayalloc((long) OTINCR * OTSIZE);
+    otn = OTINCR;
+    oti = otj = 0;
+    otarea[0] = 1, otarea[1] = 2;
+    cbfunc = func;
+    Mcouldgc = FALSE;
+}
+
+void Mterm(void)
+{
+    buffer_t *bp;
+
+#ifdef STATS
+    finsbrk = (caddr_t) sbrk(0);
+    printf("memory used by data: %ld\n", (long) (finsbrk - origsbrk));
+#endif
+
+    Marrayfree(otarray[0]), Marrayfree(otarray[1]);
+    otarray[0] = otarray[1] = NULL;
+    otn = otj = oti = 0;
+    Marrayfree(freearray), freearray = NULL, freen = 0;
+    Marrayfree(markarray), markarray = NULL, markn = marki = 0;
+    for (bp = bufferlist; bp;) {
+       free(bp->data);
+       bufferlist = bp, bp = bp->next, free(bufferlist);
+    }
+    bufferlist = NULL;
+}
+
+void *Mnew(long size, int type)
+{
+    freeobj_t *fp;
+
+    size = (size < FREEOBJSIZE) ?
+       M_BYTE2SIZE(FREEOBJSIZE) : M_BYTE2SIZE(size);
+    if (size >= freen || !freearray[size]) {
+       allocbuffer(size), numofallocs++;
+       if (numofallocs == NUMOFALLOCS)
+           Mdogc(M_GCFULL), gcsteps <<= 1, numofallocs = 0;
+       else
+           Mdogc(M_GCINCR);
+    } else if (Mgcstate == M_GCON)
+       Mdogc(M_GCINCR);
+    fp = freearray[size], freearray[size] = fp->next;
+    fp->head.type = type;
+    Mmkcurr(fp);
+    Mcouldgc = TRUE;
+
+#ifdef STATS
+    objnum++, objsiz += size;
+    typenum[type]++, typesiz[type] += size;
+#endif
+
+    return fp;
+}
+
+void *Mallocate(long size)
+{
+    freeobj_t *fp;
+
+    size = (size < FREEOBJSIZE) ?
+       M_BYTE2SIZE(FREEOBJSIZE) : M_BYTE2SIZE(size);
+    if (size >= freen || !freearray[size])
+       allocbuffer(size);
+    fp = freearray[size], freearray[size] = fp->next;
+    return fp;
+}
+
+void Mfree(void *p, long size)
+{
+    freeobj_t *fp;
+
+    fp = p;
+    fp->head.size = size;
+    fp->head.area = 0;
+    fp->head.type = 0;
+    fp->next = freearray[fp->head.size], freearray[fp->head.size] = fp;
+}
+
+#ifndef FEATURE_MS
+
+void *Marrayalloc(long size)
+{
+    void *p;
+
+    if (!(p = malloc(size)))
+       panic(POS, "Marrayallocate", "cannot allocate array");
+    return p;
+}
+
+void *Marraygrow(void *p, long size)
+{
+    if (!(p = realloc(p, size)))
+       panic(POS, "Marrayreallocate", "cannot re-allocate array");
+    return p;
+}
+
+void Marrayfree(void *p)
+{
+    free(p);
+}
+
+#else
+
+static struct arraymap_t {
+    HGLOBAL k;
+    void *v;
+} arraymap[100];
+
+void *Marrayalloc(long size)
+{
+    int i;
+
+    for (i = 0; i < 100; i++)
+       if (!arraymap[i].k)
+           break;
+    if (i == 100)
+       panic(POS, "Marrayalloc", "out of space in arraymap");
+    if (!(arraymap[i].k = GlobalAlloc(GPTR, size)))
+       panic(POS, "Marrayallocate", "cannot allocate array");
+    arraymap[i].v = GlobalLock(arraymap[i].k);
+    return arraymap[i].v;
+}
+
+void *Marraygrow(void *p, long size)
+{
+    int i;
+
+    for (i = 0; i < 100; i++)
+       if (arraymap[i].v == p)
+           break;
+    if (i == 100)
+       panic(POS, "Marraygrow", "cannot locate pointer");
+    if (!
+       (arraymap[i].k =
+        GlobalReAlloc(arraymap[i].k, size, GMEM_MOVEABLE)))
+       panic(POS, "Marraygrow", "cannot re-allocate array");
+    arraymap[i].v = GlobalLock(arraymap[i].k);
+    return arraymap[i].v;
+}
+
+void Marrayfree(void *p)
+{
+    int i;
+
+    for (i = 0; i < 100; i++)
+       if (arraymap[i].v == p)
+           break;
+    if (i == 100)
+       panic(POS, "Marrayfree", "cannot locate pointer");
+    GlobalUnlock(arraymap[i].k);
+    GlobalFree(arraymap[i].k);
+    arraymap[i].k = 0;
+}
+
+#endif
+
+long Mpushmark(void *p)
+{
+    if (marki == markn) {
+       markarray = Marraygrow(markarray,
+                              (long) (markn + MARKINCR) * MARKSIZE);
+       markn += MARKINCR;
+    }
+    markarray[marki++] = p;
+    if (Mgcstate == M_GCON)
+       Mmkcurr(p);
+    return marki - 1;
+}
+
+void Mpopmark(long m)
+{
+    marki = m;
+}
+
+void Mresetmark(long m, void *p)
+{
+    markarray[m] = p;
+    if (Mgcstate == M_GCON)
+       Mmkcurr(p);
+}
+
+void Mmkcurr(void *p)
+{
+    if (!p || M_AREAOF(p) == otarea[0])
+       return;
+    if (oti >= otn) {
+       otarray[0] =
+           Marraygrow(otarray[0], (long) (otn + OTINCR) * OTSIZE);
+       otarray[1] =
+           Marraygrow(otarray[1], (long) (otn + OTINCR) * OTSIZE);
+       otn += OTINCR;
+    }
+    otarray[0][oti++] = p;
+    ((Mheader_t *) p)->area = otarea[0];
+}
+
+void Mdogc(Mgctype_t gctype)
+{
+    void *p;
+    long i;
+    char n;
+    static long prevoti;
+
+    if (Mgcstate == M_GCOFF) {
+       Mgcstate = M_GCON;
+       p = otarray[0], otarray[0] = otarray[1], otarray[1] = p;
+       n = otarea[0], otarea[0] = otarea[1], otarea[1] = n;
+       prevoti = oti, oti = otj = 0;
+       for (i = 0; i < marki; i++)
+           Mmkcurr(markarray[i]);
+    }
+    if (gctype == M_GCFULL) {
+       while (otj != oti) {
+           p = otarray[0][otj];
+           if (Mhaspointers[M_TYPEOF(p)])
+               Tgchelper(p);
+           otj++;
+       }
+    } else {
+       for (i = 0; i < gcsteps && otj != oti; i++) {
+           p = otarray[0][otj];
+           if (Mhaspointers[M_TYPEOF(p)])
+               Tgchelper(p);
+           otj++;
+       }
+       if (otj < oti)
+           return;
+    }
+    for (i = 0; i < prevoti; i++) {
+       p = otarray[1][i];
+       if (p && M_AREAOF(p) == otarea[1]) {
+           if (Mhaspointers[M_TYPEOF(p)])
+               Tfreehelper(p);
+           Mfree(p, (long) ((Mheader_t *) p)->size);
+       }
+    }
+    if (gctype == M_GCINCR) {
+       if (numofallocs < NUMOFALLOCS / 2) {
+           int t = (gcsteps > GCINCRSTEPS) ? gcsteps >>= 1 : GCINCRSTEPS;
+           gcsteps = t;
+           numofallocs = 0;
+       }
+    }
+    if (cbfunc)
+       (*cbfunc) ();
+    Mgcstate = M_GCOFF;
+    Mcouldgc = FALSE;
+}
+
+void Mreport(void)
+{
+    Mheader_t *p;
+    long num[M_MAXTYPES], siz[M_MAXTYPES];
+    long i, n;
+    freeobj_t *fp;
+
+    Mdogc(M_GCFULL);
+    Mdogc(M_GCFULL);
+    for (i = 0; i < M_MAXTYPES; i++)
+       num[i] = siz[i] = 0;
+    for (i = 0; i < oti; i++) {
+       p = otarray[0][i];
+       siz[0] += p->size;
+       siz[M_TYPEOF(p)] += p->size;
+       num[M_TYPEOF(p)]++;
+       num[0]++;
+    }
+    fprintf(stderr, "live objects:      %8ld (", num[0]);
+    for (i = 1; i < M_MAXTYPES; i++)
+       fprintf(stderr, "%8ld%s", num[i],
+               (i == M_MAXTYPES - 1) ? "" : ",");
+    fprintf(stderr, ")\n       sizes:      %8ld (", siz[0]);
+    for (i = 1; i < M_MAXTYPES; i++)
+       fprintf(stderr, "%8ld%s", siz[i],
+               (i == M_MAXTYPES - 1) ? "" : ",");
+    fprintf(stderr, ")\n");
+    fprintf(stderr, "free lists: %ld\n", freen);
+    for (i = 0; i < freen; i++) {
+       for (n = 0, fp = freearray[i]; fp; fp = fp->next)
+           n++;
+       if (n > 0)
+           fprintf(stderr, "free list: %ld - %ld\n", i, n);
+    }
+#ifdef STATS
+    printf("objects allocated: %8ld (", objnum);
+    for (i = 1; i < M_MAXTYPES; i++)
+       printf("%l8d%s", typenum[i], (i == M_MAXTYPES - 1) ? "" : ",");
+    printf(")\n            sizes: %8ld (", objsiz);
+    for (i = 1; i < M_MAXTYPES; i++)
+       printf("%8ld%s", typesiz[i], (i == M_MAXTYPES - 1) ? "" : ",");
+    printf(")\n");
+    finsbrk = (caddr_t) sbrk(0);
+    printf("memory used by data: %ld\n", (long) (finsbrk - origsbrk));
+#endif
+}
+
+static void allocbuffer(long size)
+{
+    buffer_t *bp;
+    char *p;
+    long i, bytes, n;
+
+    if (size >= freen) {
+       if (size > M_SIZEMAX)
+           panic(POS, "allocbuffer", "size is too big");
+       freearray = Marraygrow(freearray, (long) (size + 1) * FREESIZE);
+       for (i = freen; i < size + 1; i++)
+           freearray[i] = NULL;
+       freen = size + 1;
+    }
+    n = CALCNUM(size);
+    if (!freearray[size]) {
+       if (!(bp = malloc(BUFFERSIZE)))
+           panic(POS, "allocbuffer", "cannot allocate buffer struct");
+       if (!(bp->data = malloc(size * M_UNITSIZE * n)))
+           panic(POS, "allocbuffer", "cannot allocate buffer");
+       bp->next = bufferlist, bufferlist = bp;
+       bytes = size * M_UNITSIZE;
+       for (i = 0, p = bp->data; i < n - 1; i++, p += bytes) {
+           ((freeobj_t *) p)->next = p + bytes;
+           ((freeobj_t *) p)->head.size = (Msize_t) size;
+           ((freeobj_t *) p)->head.area = 0;
+           ((freeobj_t *) p)->head.type = 0;
+       }
+       ((freeobj_t *) p)->next = NULL;
+       ((freeobj_t *) p)->head.size = (Msize_t) size;
+       ((freeobj_t *) p)->head.area = 0;
+       ((freeobj_t *) p)->head.type = 0;
+       freearray[size] = bp->data;
+    }
+}
diff --git a/cmd/lefty/mem.h b/cmd/lefty/mem.h
new file mode 100644 (file)
index 0000000..17ba9f9
--- /dev/null
@@ -0,0 +1,76 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Lefteris Koutsofios - AT&T Bell Laboratories */
+
+#ifndef _MEM_H
+#define _MEM_H
+
+#ifdef FEATURE_MINTSIZE
+    typedef int Msize_t;
+#define M_SIZEMAX INT_MAX
+#else
+    typedef short Msize_t;
+#define M_SIZEMAX SHRT_MAX
+#endif
+    typedef struct Mheader_t {
+       char type;
+       char area;
+       Msize_t size;
+    } Mheader_t;
+#define M_HEADERSIZE sizeof (Mheader_t)
+
+    typedef enum {
+       M_GCOFF, M_GCON
+    } Mgcstate_t;
+
+    typedef enum {
+       M_GCFULL, M_GCINCR
+    } Mgctype_t;
+
+#define M_UNITSIZE sizeof (long)
+#define M_BYTE2SIZE(l) ((long) (((l + M_UNITSIZE - 1) / M_UNITSIZE)))
+#define M_AREAOF(p) ((int) (((Mheader_t *) p)->area))
+#define M_TYPEOF(p) ((int) (((Mheader_t *) p)->type))
+
+    extern int Mhaspointers[];
+    extern Mgcstate_t Mgcstate;
+    extern int Mcouldgc;
+
+    void Minit(void (*)(void));
+    void Mterm(void);
+    void *Mnew(long, int);
+    void *Mallocate(long);
+    void Mfree(void *, long);
+    void *Marrayalloc(long);
+    void *Marraygrow(void *, long);
+    void Marrayfree(void *);
+    long Mpushmark(void *);
+    void Mpopmark(long);
+    void Mresetmark(long, void *);
+    void Mmkcurr(void *);
+    void Mdogc(Mgctype_t);
+    void Mreport(void);
+#endif                         /* _MEM_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cmd/lefty/os/.cvsignore b/cmd/lefty/os/.cvsignore
new file mode 100644 (file)
index 0000000..9fb9857
--- /dev/null
@@ -0,0 +1,6 @@
+*.la
+*.lo
+.deps
+.libs
+Makefile
+Makefile.in
diff --git a/cmd/lefty/os/Makefile.am b/cmd/lefty/os/Makefile.am
new file mode 100644 (file)
index 0000000..08d53d0
--- /dev/null
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = unix
+
+EXTRA_DIST = mswin32/lefty.mak mswin32/doinst mswin32/io.c