--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = ws os cs2l dot2l examples
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/lefty/ws/x11 \
+ -I$(top_srcdir)/lefty/os/unix \
+ -I$(top_srcdir)/lefty/dot2l @XAW_INCLUDES@
+
+man = lefty.1
+pdf = lefty.pdf
+
+leftydir = $(pkgdatadir)/lefty
+pdfdir = $(pkgdatadir)/doc/pdf
+
+AM_CFLAGS = -DLEFTYPATH=\"$(leftydir)\" -DHAVEDOT @X_CFLAGS@
+
+noinst_HEADERS = code.h common.h display.h exec.h g.h gfxview.h internal.h \
+ io.h lex.h mem.h parse.h str.h tbl.h txtview.h
+if WITH_X
+bin_PROGRAMS = lefty
+man_MANS = $(man)
+pdf_DATA = $(pdf)
+endif
+
+lefty_SCRIPTS = lefty.psp
+
+lefty_SOURCES = code.c common.c display.c exec.c g.c gfxview.c internal.c \
+ lefty.c lex.c mem.c parse.c str.c tbl.c txtview.c
+
+#
+# NB. -lXaw must be before -lXt or strange inability-to-get-mouse-focus
+# problems can occur on some systems.
+#
+lefty_LDADD = $(top_builddir)/lefty/dot2l/libdot2l.la \
+ $(top_builddir)/lefty/ws/x11/libws.la \
+ $(top_builddir)/lefty/ws/x11/libfilereq/libfilereq.la \
+ $(top_builddir)/lefty/os/unix/libos.la \
+ @X_LIBS@ @XAW_LIBS@ @X_PRE_LIBS@ @XPM_LIBS@ \
+ -lXt -lXmu -lXext -lX11 @SOCKET_LIBS@ @MATH_LIBS@
+
+.1.pdf:
+ groff -Tps -man $< | ps2pdf - - >$@
+
+EXTRA_DIST = $(lefty_SCRIPTS) $(lefty_SOURCES) $(man) $(pdf) \
+ colors.txt Makefile.old aix_mods
+
+DISTCLEANFILES = $(pdf)
--- /dev/null
+all: lefty
+
+include ../Config.mk
+include ../makearch/$(ARCH)
+
+DOT2L = dot2l
+WM = ws/x11
+OS = os/unix
+
+LEFTYLIBDIR= $(LIBDIR)/lefty
+DEFINES=-DLEFTYPATH=\"$(LEFTYLIBDIR)\" -DHAVEDOT -DHAVE_CONFIG_H
+
+INCS = -I. -I.. \
+ -I$(DOT2L) \
+ -I$(X11INC) \
+ -I$(WM) \
+ -I$(WM)/libfilereq \
+ -I$(OS)
+
+DOT2LEFTYSRC = $(DOT2L)/dotparse.y $(DOT2L)/dot2l.c \
+ $(DOT2L)/dotlex.c $(DOT2L)/dottrie.c
+DOT2LEFTYOBJ = dotparse.o dot2l.o dotlex.o dottrie.o
+
+OSSRC = $(OS)/io.c
+OSOBJ = io.o
+
+SRCS = lefty.c gfxview.c txtview.c internal.c display.c str.c exec.c parse.c \
+ lex.c $(DOT2LEFTYSRC) tbl.c code.c
+
+OBJS = lefty.o gfxview.o txtview.o internal.o display.o str.o exec.o parse.o \
+ lex.o $(DOT2LEFTYOBJ) tbl.o code.o io.o
+
+GSRC = g.c gcommon.c garray.c gbutton.c gcanvas.c glabel.c gmenu.c \
+ gpcanvas.c gquery.c gscroll.c gtext.c gview.c mem.c common.c \
+ SelFile.c Draw.c Path.c Dir.c
+
+GSRC = g.c $(WM)/gcommon.c $(WM)/garray.c $(WM)/gbutton.c $(WM)/gcanvas.c \
+ $(WM)/glabel.c $(WM)/gmenu.c $(WM)/gpcanvas.c $(WM)/gquery.c \
+ $(WM)/gscroll.c $(WM)/gtext.c $(WM)/gview.c mem.c common.c \
+ $(WM)/libfilereq/SelFile.c $(WM)/libfilereq/Draw.c \
+ $(WM)/libfilereq/Path.c $(WM)/libfilereq/Dir.c
+
+GOBJS = g.o gcommon.o garray.o gbutton.o gcanvas.o glabel.o gmenu.o \
+ gpcanvas.o gquery.o gscroll.o gtext.o gview.o mem.o common.o \
+ SelFile.o Draw.o Path.o Dir.o
+
+lefty: $(OBJS) libgfx.a
+ $(CC) $(LDFLAGS) -L. -L$(X11LIB) $(OBJS) -lgfx -lXaw -lXmu -lXt -lXext -lX11 -lm $(LEFTYLIBS) -o lefty
+
+libgfx.a : $(GOBJS)
+ $(AR) cr libgfx.a $(GOBJS)
+
+# lefty.static is not completely static because we don't want to
+# bind libc unnecessarily. we mostly wanted to bind things like X11
+# and tcl that are likely to cause headaches when porting binaries.
+lefty.static : lefty.static.$(ARCH)
+
+lefty.static.linux: $(OBJS)
+ $(CC) -o lefty $(OBJS) \
+ $(X11LIB)/libXaw.a $(X11LIB)/libXmu.a $(X11LIB)/libXt.a \
+ $(X11LIB)/libXext.a $(X11LIB)/libX11.a $(X11LIB)/libSM.a \
+ $(X11LIB)/libICE.a -lm
+
+lefty.static.hp.pa: $(OBJS)
+ $(CC) $(LDFLAGS) -o lefty $(OBJS) \
+ $(HOME)/lib/libXaw.a $(HOME)/lib/libXmu.a $(X11LIB)/libXt.a \
+ $(X11LIB)/libXext.a $(X11LIB)/libX11.a -lm
+
+lefty.static.sol.sun4: $(OBJS)
+ $(CC) -o lefty $(OBJS) \
+ $(X11LIB)/libXaw.a $(X11LIB)/libXmu.a $(X11LIB)/libXt.a \
+ $(X11LIB)/libX11.a $(X11LIB)/libXext.a \
+ -ldl /lib/libsocket.a /lib/libnsl.a /lib/libw.a /lib/libintl.a -lm
+
+lefty.static.sun4: $(OBJS)
+ $(CC) -o lefty $(OBJS) \
+ $(X11LIB)/libXaw.a $(X11LIB)/libXmu.a $(X11LIB)/libXt.a \
+ $(X11LIB)/libX11.a $(X11LIB)/libXext.a -lm
+
+dot2l.o: $(DOT2L)/dot2l.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+dotlex.o: $(DOT2L)/dotlex.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+dottrie.o: $(DOT2L)/dottrie.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gcommon.o: $(WM)/gcommon.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+garray.o: $(WM)/garray.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gbutton.o: $(WM)/gbutton.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gcanvas.o: $(WM)/gcanvas.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+glabel.o: $(WM)/glabel.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gmenu.o: $(WM)/gmenu.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gpcanvas.o: $(WM)/gpcanvas.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gquery.o: $(WM)/gquery.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gscroll.o: $(WM)/gscroll.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gtext.o: $(WM)/gtext.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+gview.o: $(WM)/gview.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+Dir.o: $(WM)/libfilereq/Dir.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+Draw.o: $(WM)/libfilereq/Draw.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+Path.o: $(WM)/libfilereq/Path.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+SelFile.o: $(WM)/libfilereq/SelFile.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+io.o: $(OS)/io.c
+ $(CC) -c $(CCFLAGS) $(INCS) $(DEFINES) $?
+
+dotparse.c: $(DOT2L)/dotparse.y
+ $(YACC) -d $(DOT2L)/dotparse.y
+ $(MV) y.tab.c dotparse.c
+ $(MV) y.tab.h dotparse.h
+
+dotparse.o: dotparse.c
+
+install: lefty
+ $(MKPATH) $(BINDIR)
+ $(INSTALL) lefty $(BINDIR)
+ $(MKPATH) $(MANDIR)
+ $(INSTALL) lefty.1 $(MANDIR)
+ $(MKPATH) $(LIBDIR)
+ $(INSTALL) libgfx.a $(LIBDIR)
+ $(MKPATH) $(LIBDIR)/lefty
+ $(INSTALL) lefty.psp $(LIBDIR)/lefty
+
+clean:
+ $(RM) core *.o dotparse.[ch]
+
+distclean: clean
+ $(RM) lefty *.a
--- /dev/null
+/* $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 _COMMON_H
+#define _COMMON_H
+#ifdef HAVECS
+#include <ast.h>
+#else
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include <sys/select.h>
+#include <math.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <ctype.h>
+
+#ifdef MSWIN32
+#include <windows.h>
+#include <commdlg.h>
+#include <malloc.h>
+#endif
+
+#define POS __FILE__, __LINE__
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifndef L_SUCCESS
+#define L_SUCCESS 1
+#define L_FAILURE 0
+#endif
+
+#define CHARSRC 0
+#define FILESRC 1
+
+/*#define M_PI 3.14159265358979323846 */
+
+#ifndef REALSTRCMP
+#define Strcmp(s1, s2) ( \
+ *(s1) == *(s2) ? ( \
+ (*s1) ? strcmp ((s1) + 1, (s2) + 1) : 0 \
+ ) : (*(s1) < *(s2) ? -1 : 1) \
+)
+#else
+#define Strcmp(s1, s2) strcmp ((s1), (s2))
+#endif
+
+ extern int warnflag;
+ extern char *leftypath, *leftyoptions, *shellpath;
+ extern jmp_buf exitljbuf;
+ extern int idlerunmode;
+ extern fd_set inputfds;
+
+ int init(char *);
+ void term(void);
+ char *buildpath(char *, int);
+ char *buildcommand(char *, char *, int, int, char *);
+ void warning(char *, int, char *, char *, ...);
+ void panic(char *, int, char *, char *, ...);
+ void panic2(char *, int, char *, char *, ...);
+#endif /* _COMMON_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* $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"
+#include "code.h"
+#include "tbl.h"
+#include "str.h"
+#include "exec.h"
+#include "internal.h"
+
+static lvar_t *lvarp;
+static int lvarn, llvari, flvari;
+#define LVARINCR 1000
+#define LVARSIZE sizeof (lvar_t)
+
+Tobj root, null;
+Tobj rtno;
+int Erun;
+int Eerrlevel, Estackdepth, Eshowbody, Eshowcalls, Eoktorun;
+
+#define PUSHJMP(op, np, b) op = (volatile jmp_buf *) np, np = (jmp_buf *) &b
+#define POPJMP(op, np) np = (jmp_buf *) op
+
+/* longjmps for normal program execution */
+typedef enum {
+ PLJ_BREAK, PLJ_CONTINUE, PLJ_RETURN, PLJ_SIZE
+} PLJtype_t;
+static jmp_buf *pljbufp1, *pljbufp2;
+static PLJtype_t pljtype;
+
+/* longjmp for error handling */
+static jmp_buf *eljbufp;
+
+/* error levels and types */
+typedef enum {
+ ERR0, ERR1, ERR2, ERR3, ERR4, ERR5
+} errlevel_t;
+typedef enum {
+ ERRNOLHS, ERRNORHS, ERRNOSUCHFUNC, ERRBADARG, ERRARGMIS, ERRNOTATABLE,
+ ERRIFUNCERR, ERRRECRUN, ERRTABLECHANGED
+} errnum_t;
+static char *errnam[] = {
+ "no variable",
+ "no value",
+ "no such function",
+ "bad argument",
+ "argument number mismatch",
+ "not a table",
+ "internal function call error",
+ "recursive run attempt",
+ "table changed during a forin loop",
+};
+
+static int errdo;
+
+/* stack information */
+typedef struct sinfo_t {
+ Tobj co, fco;
+ int ci, fci;
+ int flvari, llvari;
+} sinfo_t;
+#define SINFOSIZE sizeof (sinfo_t)
+#define SINFOINCR 100
+static sinfo_t *sinfop;
+static int sinfoi, sinfon;
+
+typedef enum {
+ TNK_LI, TNK_O, TNK_S
+} tnktype_t;
+typedef struct tnk_t {
+ tnktype_t type;
+ union {
+ int li;
+ struct {
+ Tobj to, ko;
+ } tnko;
+ struct {
+ Ctype_t kt;
+ Tobj to, co;
+ int vi;
+ } tnks;
+ } u;
+} tnk_t;
+
+typedef struct num_tt {
+ Ctype_t type;
+ union {
+ long i;
+ double d;
+ Tobj no;
+ } u;
+} num_tt;
+
+static long rootm;
+static int running;
+
+static Tobj eeval(Tobj, int);
+static Tobj efcall(Tobj, int);
+static void ewhilest(Tobj, int);
+static void eforst(Tobj, int);
+static void eforinst(Tobj, int);
+
+static Tobj getval(Tobj, int);
+static int getvar(Tobj, int, tnk_t *);
+static void setvar(tnk_t, Tobj);
+static int boolop(Tobj);
+static int orderop(Tobj, Ctype_t, Tobj);
+static Tobj arithop(num_tt *, Ctype_t, num_tt *);
+static void err(int, int, Tobj, int);
+static void printbody(char *, int);
+
+void Einit(void)
+{
+ root = Ttable(100);
+ rootm = Mpushmark(root);
+ Tinss(root, "null", (null = Ttable(2)));
+ rtno = NULL;
+ pljbufp1 = pljbufp2 = NULL, pljtype = 0;
+ eljbufp = NULL;
+ lvarp = Marrayalloc((long) LVARINCR * LVARSIZE);
+ lvarn = LVARINCR;
+ llvari = 0;
+ flvari = 0;
+ sinfop = Marrayalloc((long) SINFOINCR * SINFOSIZE);
+ sinfon = SINFOINCR;
+ sinfoi = 0;
+ Erun = FALSE;
+ running = 0;
+ Eoktorun = FALSE;
+}
+
+void Eterm(void)
+{
+ Marrayfree(sinfop), sinfop = NULL, sinfon = 0, sinfoi = 0;
+ Marrayfree(lvarp), lvarp = NULL, lvarn = 0, llvari = 0, flvari = 0;
+ rtno = NULL;
+ null = NULL;
+ Mpopmark(rootm);
+}
+
+Tobj Eunit(Tobj co)
+{
+ volatile jmp_buf *oeljbufp;
+ volatile int ownsinfoi;
+ volatile long m;
+ volatile Tobj lrtno;
+
+ jmp_buf eljbuf;
+
+#if 0
+ if (running && !Eoktorun) {
+ err(ERRRECRUN, ERR2, NULL, 0);
+ return NULL;
+ }
+#endif
+ Eoktorun = FALSE;
+
+ if (!co)
+ return NULL;
+
+ if (Tgettype(co) != T_CODE)
+ panic(POS, "Eunit", "argument type is not T_CODE");
+
+ m = Mpushmark(co);
+ PUSHJMP(oeljbufp, eljbufp, eljbuf);
+ ownsinfoi = sinfoi++;
+ if (sinfoi == sinfon) {
+ sinfop =
+ Marraygrow(sinfop, (long) (sinfon + SINFOINCR) * SINFOSIZE);
+ sinfon += SINFOINCR;
+ }
+ sinfop[ownsinfoi].co = co;
+ sinfop[ownsinfoi].ci = TCgetfp(co, 0);
+ sinfop[ownsinfoi].fco = NULL;
+ sinfop[ownsinfoi].flvari = flvari;
+ sinfop[ownsinfoi].llvari = llvari;
+ running++;
+ if (setjmp(*eljbufp))
+ lrtno = NULL;
+ else
+ lrtno = eeval(co, TCgetfp(co, 0));
+ running--;
+ rtno = NULL;
+ flvari = sinfop[ownsinfoi].flvari;
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ POPJMP(oeljbufp, eljbufp);
+ Mpopmark(m);
+ Erun = TRUE;
+ return lrtno;
+}
+
+/* shortcut: this function executes a piece of code that corresponds to
+ <internal func name> = function () internal "<internal func name>";
+*/
+Tobj Efunction(Tobj co, char *ifnam)
+{
+ Tobj v1o;
+ int fi;
+
+ fi = TCgetnext(co, TCgetfp(co, TCgetfp(co, 0)));
+ v1o = Tcode(TCgetaddr(co, fi), fi,
+ (int) TCgetinteger(co, TCgetfp(co, fi)));
+ Tinss(root, ifnam, v1o);
+ return v1o;
+}
+
+static Tobj eeval(Tobj co, int ci)
+{
+ Tobj v1o, v2o, v3o;
+ Ttype_t ttype;
+ Ctype_t ctype;
+ tnk_t tnk;
+ num_tt lnum, rnum;
+ long m1, m2;
+ int i1, i2, res;
+
+ tailrec:
+ errdo = TRUE;
+ v1o = NULL;
+ ctype = TCgettype(co, ci);
+ switch (ctype) {
+ case C_ASSIGN:
+ i1 = TCgetfp(co, ci);
+ if ((v1o = eeval(co, TCgetnext(co, i1))) == NULL) {
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ return NULL;
+ }
+ m1 = Mpushmark(v1o);
+ res = getvar(co, i1, &tnk);
+ Mpopmark(m1);
+ if (res == -1) {
+ err(ERRNOLHS, ERR3, co, i1);
+ return NULL;
+ }
+ setvar(tnk, v1o);
+ return v1o;
+ case C_OR:
+ case C_AND:
+ case C_NOT:
+ i1 = TCgetfp(co, ci);
+ if ((v1o = eeval(co, i1)) == NULL)
+ err(ERRNORHS, ERR4, co, i1);
+ switch (ctype) {
+ case C_OR:
+ if (boolop(v1o) == TRUE)
+ return Ttrue;
+ if ((v1o = eeval(co, TCgetnext(co, i1))) == NULL)
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ return (boolop(v1o) == TRUE) ? Ttrue : Tfalse;
+ case C_AND:
+ if (boolop(v1o) == FALSE)
+ return Tfalse;
+ if ((v1o = eeval(co, TCgetnext(co, i1))) == NULL)
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ return (boolop(v1o) == FALSE) ? Tfalse : Ttrue;
+ case C_NOT:
+ return (boolop(v1o) == TRUE) ? Tfalse : Ttrue;
+ }
+ /* NOT REACHED */
+ return Tfalse;
+ case C_EQ:
+ case C_NE:
+ case C_LT:
+ case C_LE:
+ case C_GT:
+ case C_GE:
+ i1 = TCgetfp(co, ci);
+ if ((v1o = eeval(co, i1)) == NULL)
+ err(ERRNORHS, ERR4, co, i1);
+ else
+ m1 = Mpushmark(v1o);
+ if ((v2o = eeval(co, TCgetnext(co, i1))) == NULL)
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ if (v1o)
+ Mpopmark(m1);
+ return (orderop(v1o, ctype, v2o) == TRUE) ? Ttrue : Tfalse;
+ case C_PLUS:
+ case C_MINUS:
+ case C_MUL:
+ case C_DIV:
+ case C_MOD:
+ case C_UMINUS:
+ i1 = TCgetfp(co, ci);
+ if ((lnum.type = TCgettype(co, i1)) == C_INTEGER)
+ lnum.u.i = TCgetinteger(co, i1);
+ else if (lnum.type == C_REAL)
+ lnum.u.d = TCgetreal(co, i1);
+ else if ((lnum.u.no = eeval(co, i1)) == NULL) {
+ err(ERRNORHS, ERR4, co, i1);
+ return NULL;
+ }
+ if (ctype == C_UMINUS) {
+ if (!(v1o = arithop(&lnum, ctype, NULL)))
+ err(ERRNORHS, ERR4, co, ci);
+ return v1o;
+ }
+ if (lnum.type != C_INTEGER && lnum.type != C_REAL)
+ m1 = Mpushmark(lnum.u.no);
+ i1 = TCgetnext(co, i1);
+ if ((rnum.type = TCgettype(co, i1)) == C_INTEGER)
+ rnum.u.i = TCgetinteger(co, i1);
+ else if (rnum.type == C_REAL)
+ rnum.u.d = TCgetreal(co, i1);
+ else if ((rnum.u.no = eeval(co, i1)) == NULL)
+ err(ERRNORHS, ERR4, co, i1);
+ if (lnum.type != C_INTEGER && lnum.type != C_REAL)
+ Mpopmark(m1);
+ if (!(v1o = arithop(&lnum, ctype, &rnum)))
+ err(ERRNORHS, ERR4, co, ci);
+ return v1o;
+ case C_PEXPR:
+ ci = TCgetfp(co, ci);
+ goto tailrec;
+ case C_FCALL:
+ return efcall(co, ci);
+ case C_INTEGER:
+ return Tinteger(TCgetinteger(co, ci));
+ case C_REAL:
+ return Treal(TCgetreal(co, ci));
+ case C_STRING:
+ return Tstring(TCgetstring(co, ci));
+ case C_GVAR:
+ case C_LVAR:
+ case C_PVAR:
+ return getval(co, ci);
+ case C_FUNCTION:
+ return Tcode(TCgetaddr(co, ci), ci,
+ (int) TCgetinteger(co, TCgetfp(co, ci)));
+ case C_TCONS:
+ v1o = Ttable(0);
+ m1 = Mpushmark(v1o);
+ for (i1 = TCgetfp(co, ci); i1 != C_NULL;
+ i1 = TCgetnext(co, TCgetnext(co, i1))) {
+ if (!(v3o = eeval(co, TCgetnext(co, i1)))) {
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ continue;
+ }
+ m2 = Mpushmark(v3o);
+ if (!(v2o = eeval(co, i1))) {
+ err(ERRNOLHS, ERR3, co, i1);
+ Mpopmark(m2);
+ continue;
+ }
+ ttype = Tgettype(v2o);
+ if (ttype == T_INTEGER || ttype == T_REAL || ttype == T_STRING)
+ Tinso(v1o, v2o, v3o);
+ else
+ err(ERRNOLHS, ERR1, co, i1);
+ }
+ Mpopmark(m1);
+ return v1o;
+ case C_STMT:
+ for (i1 = TCgetfp(co, ci); i1 != C_NULL;)
+ if ((i2 = TCgetnext(co, i1)) != C_NULL) {
+ eeval(co, i1);
+ i1 = i2;
+ } else {
+ ci = i1;
+ goto tailrec;
+ }
+ /* NOT REACHED */
+ break;
+ case C_IF:
+ i1 = TCgetfp(co, ci);
+ if (!(v1o = eeval(co, i1)))
+ err(ERRNORHS, ERR5, co, i1);
+ if (boolop(v1o) == TRUE) {
+ ci = TCgetnext(co, i1);
+ goto tailrec;
+ } else if ((ci = TCgetnext(co, TCgetnext(co, i1))) != C_NULL)
+ goto tailrec;
+ break;
+ case C_WHILE:
+ ewhilest(co, ci);
+ break;
+ case C_FOR:
+ eforst(co, ci);
+ break;
+ case C_FORIN:
+ eforinst(co, ci);
+ break;
+ case C_BREAK:
+ pljtype = PLJ_BREAK;
+ longjmp(*pljbufp1, 1);
+ /* NOT REACHED */
+ break;
+ case C_CONTINUE:
+ pljtype = PLJ_CONTINUE;
+ longjmp(*pljbufp1, 1);
+ /* NOT REACHED */
+ break;
+ case C_RETURN:
+ if ((i1 = TCgetfp(co, ci)) != C_NULL)
+ rtno = eeval(co, i1);
+ pljtype = PLJ_RETURN;
+ longjmp(*pljbufp2, 1);
+ /* NOT REACHED */
+ break;
+ default:
+ panic(POS, "eeval", "unknown program token type %d", ctype);
+ }
+ return v1o;
+}
+
+static Tobj efcall(Tobj co, int ci)
+{
+ volatile jmp_buf *opljbufp1, *opljbufp2;
+ volatile long m;
+ volatile int bi, ownsinfoi, li, ln;
+
+ jmp_buf pljbuf;
+ Tobj fdo, vo, lrtno;
+ int i, fci, ai, di, di1, fid;
+
+ ownsinfoi = sinfoi++;
+ if (sinfoi == sinfon) {
+ sinfop =
+ Marraygrow(sinfop, (long) (sinfon + SINFOINCR) * SINFOSIZE);
+ sinfon += SINFOINCR;
+ }
+ sinfop[ownsinfoi].co = co;
+ sinfop[ownsinfoi].ci = ci;
+ sinfop[ownsinfoi].fco = NULL;
+ sinfop[ownsinfoi].flvari = flvari;
+ sinfop[ownsinfoi].llvari = llvari;
+ fci = TCgetfp(co, ci);
+ if (!(fdo = getval(co, fci)) || Tgettype(fdo) != T_CODE) {
+ err(ERRNOSUCHFUNC, ERR2, co, fci);
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+
+ m = Mpushmark((Tobj) fdo);
+ ai = TCgetfp(co, TCgetnext(co, fci));
+ ln = (int) TCgetinteger(fdo, (li = TCgetnext(fdo, TCgetfp(fdo, 0))));
+ di = TCgetnext(fdo, li);
+ bi = TCgetnext(fdo, di);
+ if (bi != C_NULL && TCgettype(fdo, bi) == C_INTERNAL) {
+ for (i = 0; ai != C_NULL; ai = TCgetnext(co, ai), i++) {
+ if (!(vo = eeval(co, ai))) {
+ err(ERRBADARG, ERR2, co, ai);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ if (llvari + 1 > lvarn) {
+ lvarp = Marraygrow(lvarp, (long) (llvari + 1) * LVARSIZE);
+ lvarn = llvari + 1;
+ }
+ lvarp[llvari].m = Mpushmark((lvarp[llvari].o = vo));
+ llvari++;
+ }
+ fid = (int) TCgetinteger(fdo, TCgetfp(fdo, bi));
+ if (Ifuncs[fid].min > i || Ifuncs[fid].max < i) {
+ err(ERRARGMIS, ERR2, co, ci);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ flvari = sinfop[ownsinfoi].llvari;
+ sinfop[ownsinfoi].fco = fdo;
+ sinfop[ownsinfoi].fci = bi;
+ if (fid < 0 || fid >= Ifuncn)
+ panic(POS, "efcall", "no such internal function: %d", fid);
+ rtno = Ttrue;
+ if ((*Ifuncs[fid].func) (i, &lvarp[flvari]) == L_FAILURE) {
+ rtno = NULL;
+ err(ERRIFUNCERR, ERR2, co, ci);
+ }
+ } else {
+ if (llvari + ln > lvarn) {
+ lvarp = Marraygrow(lvarp, (long) (llvari + ln) * LVARSIZE);
+ lvarn = llvari + ln;
+ }
+ di1 = TCgetfp(fdo, di);
+ for (i = 0; i < ln && di1 != C_NULL && ai != C_NULL;
+ i++, ai = TCgetnext(co, ai)) {
+ if (!(vo = eeval(co, ai))) {
+ err(ERRBADARG, ERR2, co, ai);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ lvarp[llvari].m = Mpushmark((lvarp[llvari].o = vo));
+ llvari++;
+ di1 = TCgetnext(fdo, di1);
+ }
+ if (di1 != C_NULL || ai != C_NULL) {
+ err(ERRARGMIS, ERR2, co, ci);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ for (; i < ln; i++, llvari++)
+ lvarp[llvari].m = Mpushmark((lvarp[llvari].o = NULL));
+ flvari = sinfop[ownsinfoi].llvari;
+ PUSHJMP(opljbufp2, pljbufp2, pljbuf);
+ opljbufp1 = (volatile jmp_buf *) pljbufp1;
+ if (setjmp(*pljbufp2)) {
+ ;
+ } else {
+ sinfop[ownsinfoi].fco = fdo;
+ for (; bi != C_NULL; bi = TCgetnext(fdo, bi)) {
+ sinfop[ownsinfoi].fci = bi;
+ if (TCgettype(fdo, bi) != C_DECL)
+ eeval((Tobj) fdo, bi);
+ }
+ }
+ POPJMP(opljbufp2, pljbufp2);
+ pljbufp1 = (jmp_buf *) opljbufp1;
+ }
+ flvari = sinfop[ownsinfoi].flvari;
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ Mpopmark(m);
+ lrtno = rtno, rtno = NULL;
+ errdo = TRUE;
+ return lrtno;
+}
+
+static void ewhilest(Tobj co, int ci)
+{
+ volatile jmp_buf *opljbufp;
+ volatile jmp_buf pljbuf;
+ volatile Tobj c1o;
+ volatile int ei, si;
+
+ Tobj v1o;
+
+ c1o = (volatile Tobj) co; /* protect argument from longjmp */
+ ei = TCgetfp(c1o, ci);
+ si = TCgetnext(c1o, ei);
+ PUSHJMP(opljbufp, pljbufp1, pljbuf);
+ for (;;) {
+ if (!(v1o = eeval((Tobj) c1o, ei)))
+ err(ERRNORHS, ERR5, c1o, ei);
+ if (boolop(v1o) == FALSE)
+ break;
+ if (setjmp(*pljbufp1)) {
+ if (pljtype == PLJ_CONTINUE)
+ continue;
+ else if (pljtype == PLJ_BREAK)
+ break;
+ }
+ eeval((Tobj) c1o, si);
+ }
+ POPJMP(opljbufp, pljbufp1);
+}
+
+static void eforst(Tobj co, int ci)
+{
+ volatile jmp_buf *opljbufp;
+ volatile jmp_buf pljbuf;
+ volatile Tobj c1o;
+ volatile int ei1, ei2, ei3, si, eisnop1, eisnop2, eisnop3;
+
+ Tobj v1o;
+
+ c1o = (volatile Tobj) co; /* protect argument from longjmp */
+ ei1 = TCgetfp(c1o, ci);
+ ei2 = TCgetnext(c1o, ei1);
+ ei3 = TCgetnext(c1o, ei2);
+ si = TCgetnext(c1o, ei3);
+ eisnop1 = (TCgettype(c1o, ei1) == C_NOP);
+ eisnop2 = (TCgettype(c1o, ei2) == C_NOP);
+ eisnop3 = (TCgettype(c1o, ei3) == C_NOP);
+ PUSHJMP(opljbufp, pljbufp1, pljbuf);
+ if (!eisnop1)
+ eeval((Tobj) c1o, ei1);
+ for (;;) {
+ if (!eisnop2) {
+ if (!(v1o = eeval((Tobj) c1o, ei2)))
+ err(ERRNORHS, ERR5, c1o, ei2);
+ if (boolop(v1o) == FALSE)
+ break;
+ }
+ if (setjmp(*pljbufp1) != 0) {
+ if (pljtype == PLJ_CONTINUE);
+ else if (pljtype == PLJ_BREAK)
+ break;
+ } else {
+ eeval((Tobj) c1o, si);
+ }
+ if (!eisnop3)
+ eeval((Tobj) c1o, ei3);
+ }
+ POPJMP(opljbufp, pljbufp1);
+}
+
+static void eforinst(Tobj co, int ci)
+{
+ volatile jmp_buf *opljbufp;
+ volatile jmp_buf pljbuf;
+ volatile Tobj tblo, c1o;
+ volatile Tkvindex_t tkvi;
+ volatile tnk_t tnk;
+ volatile long km, t;
+ volatile int ei1, ei2, si;
+
+ c1o = (volatile Tobj) co; /* protect argument from longjmp */
+ ei1 = TCgetfp(c1o, ci);
+ ei2 = TCgetnext(c1o, ei1);
+ si = TCgetnext(c1o, ei2);
+ if (getvar((Tobj) c1o, ei1, (tnk_t *) & tnk) == -1) {
+ err(ERRNOLHS, ERR3, c1o, ei1);
+ return;
+ }
+ if (tnk.type == TNK_O)
+ km = Mpushmark(tnk.u.tnko.ko);
+ if (!(tblo = (volatile Tobj) eeval((Tobj) c1o, ei2))) {
+ if (tnk.type == TNK_O)
+ Mpopmark(km);
+ err(ERRNORHS, ERR4, c1o, ei2);
+ return;
+ }
+ if (Tgettype(tblo) != T_TABLE) {
+ err(ERRNOTATABLE, ERR1, c1o, ei2);
+ return;
+ }
+ PUSHJMP(opljbufp, pljbufp1, pljbuf);
+ t = Tgettime(tblo);
+ for (Tgetfirst((Tobj) tblo, (Tkvindex_t *) & tkvi); tkvi.kvp;
+ Tgetnext((Tkvindex_t *) & tkvi)) {
+ setvar(tnk, tkvi.kvp->ko);
+ if (setjmp(*pljbufp1) != 0) {
+ if (pljtype == PLJ_CONTINUE)
+ continue;
+ else if (pljtype == PLJ_BREAK)
+ break;
+ }
+ eeval((Tobj) c1o, si);
+ if (t != Tgettime(tblo)) {
+ err(ERRTABLECHANGED, ERR1, c1o, ei2);
+ break;
+ }
+ }
+ POPJMP(opljbufp, pljbufp1);
+ if (tnk.type == TNK_O)
+ Mpopmark(km);
+}
+
+static Tobj getval(Tobj co, int ci)
+{
+ Tobj cvo, cko, cto;
+ Ctype_t ct, vt;
+ int vi, ni, nn;
+
+ if ((ct = TCgettype(co, ci)) == C_LVAR) {
+ nn = (int) TCgetinteger(co, (ni = TCgetnext(co, TCgetfp(co, ci))));
+ cto = cvo = lvarp[flvari + nn].o;
+ if (!cto)
+ return NULL;
+ vi = TCgetnext(co, ni);
+ } else if (ct == C_GVAR) {
+ cto = root;
+ vi = TCgetfp(co, ci);
+ } else if (ct == C_PVAR)
+ return TCgetobject(co, ci);
+ else
+ return NULL;
+
+ while (vi != C_NULL) {
+ if (Tgettype(cto) != T_TABLE)
+ return NULL;
+ if ((vt = TCgettype(co, vi)) == C_STRING) {
+ if (!(cvo = Tfinds(cto, TCgetstring(co, vi))))
+ return NULL;
+ } else if (vt == C_INTEGER) {
+ if (!(cvo = Tfindi(cto, TCgetinteger(co, vi))))
+ return NULL;
+ } else if (vt == C_REAL) {
+ if (!(cvo = Tfindr(cto, TCgetreal(co, vi))))
+ return NULL;
+ } else {
+ if (!(cko = eeval(co, vi)) || !(cvo = Tfindo(cto, cko)))
+ return NULL;
+ }
+ cto = cvo;
+ vi = TCgetnext(co, vi);
+ }
+ return cvo;
+}
+
+static int getvar(Tobj co, int ci, tnk_t * tnkp)
+{
+ Tobj cvo, cko, cto;
+ Ctype_t ct, vt;
+ long m;
+ int vi, ovi, nn, ni;
+
+ if ((ct = TCgettype(co, ci)) == C_LVAR) {
+ nn = (int) TCgetinteger(co, (ni = TCgetnext(co, TCgetfp(co, ci))));
+ cvo = cto = lvarp[flvari + nn].o;
+ vi = TCgetnext(co, ni);
+ if (vi != C_NULL && (!cvo || Tgettype(cvo) != T_TABLE))
+ Mresetmark(lvarp[flvari + nn].m,
+ (lvarp[flvari + nn].o = cvo = cto = Ttable(0)));
+ } else if (ct == C_GVAR) { /* else it's a global variable */
+ cvo = root;
+ vi = TCgetfp(co, ci);
+ } else {
+ return -1;
+ }
+
+ ovi = -1;
+ while (vi != C_NULL) {
+ cto = cvo;
+ if ((vt = TCgettype(co, vi)) == C_STRING) {
+ cvo = Tfinds(cto, TCgetstring(co, vi));
+ } else if (vt == C_INTEGER) {
+ cvo = Tfindi(cto, TCgetinteger(co, vi));
+ } else if (vt == C_REAL) {
+ cvo = Tfindr(cto, TCgetreal(co, vi));
+ } else {
+ if (!(cko = eeval(co, vi)) || !(T_ISSTRING(cko) ||
+ T_ISNUMBER(cko)))
+ return -1;
+ cvo = Tfindo(cto, cko);
+ }
+ ovi = vi, vi = TCgetnext(co, vi);
+ if (vi != C_NULL && (!cvo || Tgettype(cvo) != T_TABLE)) {
+ if (vt == C_STRING)
+ Tinss(cto, TCgetstring(co, ovi), (cvo = Ttable(0)));
+ else if (vt == C_INTEGER)
+ Tinsi(cto, TCgetinteger(co, ovi), (cvo = Ttable(0)));
+ else if (vt == C_REAL)
+ Tinsr(cto, TCgetreal(co, ovi), (cvo = Ttable(0)));
+ else
+ m = Mpushmark(cko), Tinso(cto, cko, (cvo = Ttable(0))),
+ Mpopmark(m);
+ }
+ }
+ if (ct == C_LVAR && ovi == -1) {
+ tnkp->type = TNK_LI;
+ tnkp->u.li = nn;
+ } else {
+ switch (vt) {
+ case C_STRING:
+ case C_INTEGER:
+ case C_REAL:
+ tnkp->type = TNK_S;
+ tnkp->u.tnks.kt = vt;
+ tnkp->u.tnks.to = cto;
+ tnkp->u.tnks.co = co;
+ tnkp->u.tnks.vi = ovi;
+ break;
+ default:
+ tnkp->type = TNK_O;
+ tnkp->u.tnko.to = cto;
+ tnkp->u.tnko.ko = cko;
+ break;
+ }
+ }
+ return 0;
+}
+
+static void setvar(tnk_t tnk, Tobj vo)
+{
+ switch (tnk.type) {
+ case TNK_LI:
+ Mresetmark(lvarp[flvari + tnk.u.li].m,
+ (lvarp[flvari + tnk.u.li].o = vo));
+ break;
+ case TNK_O:
+ Tinso(tnk.u.tnko.to, tnk.u.tnko.ko, vo);
+ break;
+ default:
+ switch (tnk.u.tnks.kt) {
+ case C_STRING:
+ Tinss(tnk.u.tnks.to,
+ TCgetstring(tnk.u.tnks.co, tnk.u.tnks.vi), vo);
+ break;
+ case C_INTEGER:
+ Tinsi(tnk.u.tnks.to,
+ TCgetinteger(tnk.u.tnks.co, tnk.u.tnks.vi), vo);
+ break;
+ case C_REAL:
+ Tinsr(tnk.u.tnks.to, TCgetreal(tnk.u.tnks.co, tnk.u.tnks.vi),
+ vo);
+ break;
+ }
+ break;
+ }
+}
+
+static int boolop(Tobj vo)
+{
+ long i;
+ double d;
+
+ if (!vo)
+ return FALSE;
+
+ switch (Tgettype(vo)) {
+ case T_INTEGER:
+ i = Tgetinteger(vo);
+ return (i == 0) ? FALSE : TRUE;
+ case T_REAL:
+ d = Tgetreal(vo);
+ return (d == 0.0) ? FALSE : TRUE;
+ case T_TABLE:
+ if (vo == null)
+ return FALSE;
+ return TRUE;
+ default:
+ return TRUE;
+ }
+}
+
+static int orderop(Tobj v1o, Ctype_t op, Tobj v2o)
+{
+ Ctype_t t1, t2;
+ long i1, i2;
+ int r;
+ double d1, d2;
+
+ if (!v1o || !v2o) {
+ if ((v1o || v2o) && op == C_NE)
+ return TRUE;
+ return FALSE;
+ }
+ t1 = Tgettype(v1o), t2 = Tgettype(v2o);
+ if (t1 == T_STRING && t2 == T_STRING) {
+ r = Strcmp(Tgetstring(v1o), Tgetstring(v2o));
+ } else if (t1 == T_INTEGER && t2 == T_INTEGER) {
+ i1 = Tgetinteger(v1o), i2 = Tgetinteger(v2o);
+ r = (i1 == i2) ? 0 : ((i1 < i2) ? -1 : 1);
+ } else if (t1 == T_INTEGER && t2 == T_REAL) {
+ i1 = Tgetinteger(v1o), d2 = Tgetreal(v2o);
+ r = (i1 == d2) ? 0 : ((i1 < d2) ? -1 : 1);
+ } else if (t1 == T_REAL && t2 == T_INTEGER) {
+ d1 = Tgetreal(v1o), i2 = Tgetinteger(v2o);
+ r = (d1 == i2) ? 0 : ((d1 < i2) ? -1 : 1);
+ } else if (t1 == T_REAL && t2 == T_REAL) {
+ d1 = Tgetreal(v1o), d2 = Tgetreal(v2o);
+ r = (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+ } else if (t1 == t2) {
+ if (op != C_EQ && op != C_NE)
+ return FALSE;
+ r = (v1o == v2o) ? 0 : 1;
+ } else {
+ return FALSE;
+ }
+ switch (op) {
+ case C_EQ:
+ return (r == 0) ? TRUE : FALSE;
+ case C_NE:
+ return (r != 0) ? TRUE : FALSE;
+ case C_LT:
+ return (r < 0) ? TRUE : FALSE;
+ case C_LE:
+ return (r <= 0) ? TRUE : FALSE;
+ case C_GT:
+ return (r > 0) ? TRUE : FALSE;
+ case C_GE:
+ return (r >= 0) ? TRUE : FALSE;
+ }
+ panic(POS, "orderop", "bad op code");
+ return FALSE; /* NOT REACHED */
+}
+
+static Tobj arithop(num_tt * lnum, Ctype_t op, num_tt * rnum)
+{
+ double d1, d2, d3;
+
+ if (!rnum && op != C_UMINUS)
+ return NULL;
+ if (lnum->type == C_INTEGER)
+ d1 = lnum->u.i;
+ else if (lnum->type == C_REAL)
+ d1 = lnum->u.d;
+ else if (!lnum->u.no)
+ return NULL;
+ else if (Tgettype(lnum->u.no) == T_INTEGER)
+ d1 = Tgetinteger(lnum->u.no);
+ else if (Tgettype(lnum->u.no) == T_REAL)
+ d1 = Tgetreal(lnum->u.no);
+ else
+ return NULL;
+ if (op == C_UMINUS) {
+ d3 = -d1;
+ goto result;
+ }
+ if (rnum->type == C_INTEGER)
+ d2 = rnum->u.i;
+ else if (rnum->type == C_REAL)
+ d2 = rnum->u.d;
+ else if (!rnum->u.no)
+ return NULL;
+ else if (Tgettype(rnum->u.no) == T_INTEGER)
+ d2 = Tgetinteger(rnum->u.no);
+ else if (Tgettype(rnum->u.no) == T_REAL)
+ d2 = Tgetreal(rnum->u.no);
+ else
+ return NULL;
+ switch (op) {
+ case C_PLUS:
+ d3 = d1 + d2;
+ break;
+ case C_MINUS:
+ d3 = d1 - d2;
+ break;
+ case C_MUL:
+ d3 = d1 * d2;
+ break;
+ case C_DIV:
+ d3 = d1 / d2;
+ break;
+ case C_MOD:
+ d3 = (long) d1 % (long) d2;
+ break;
+ }
+ result:
+ if (d3 == (double) (long) d3)
+ return Tinteger((long) d3);
+ return Treal(d3);
+}
+
+static void err(int errnum, int level, Tobj co, int ci)
+{
+ char *s;
+ int si, i;
+
+ if (level > Eerrlevel || !errdo)
+ return;
+ s = "";
+ fprintf(stderr, "runtime error: %s\n", errnam[errnum]);
+ if (!co)
+ return;
+ if (Estackdepth < 1)
+ return;
+ if (!sinfop[(si = sinfoi - 1)].fco && si > 0)
+ si--;
+ if (Eshowbody > 0) {
+ if (co == sinfop[si].fco)
+ s = Scfull(co, 0, ci);
+ else if (co == sinfop[si].co)
+ s = Scfull(co, TCgetfp(co, 0), ci);
+ printbody(s, Eshowbody), free(s);
+ if (Estackdepth == 1) {
+ fprintf(stderr, "\n");
+ errdo = FALSE;
+ }
+ for (i = si; i >= 0; i--) {
+ if (sinfop[i].fco) {
+ s = Scfull(sinfop[i].fco, 0, sinfop[i].fci);
+ printbody(s, Eshowbody), free(s);
+ }
+ }
+ s = Scfull(sinfop[0].co, TCgetfp(sinfop[0].co, 0), sinfop[0].ci);
+ printbody(s, Eshowbody), free(s);
+ }
+ fprintf(stderr, "\n");
+ errdo = FALSE;
+}
+
+static void printbody(char *s, int mode)
+{
+ char *s1, *s2;
+ char c;
+
+ if (mode == 2) {
+ fprintf(stderr, "%s\n", s);
+ return;
+ }
+ c = '\000';
+ for (s1 = s; *s1; s1++)
+ if (*s1 == '>' && *(s1 + 1) && *(s1 + 1) == '>')
+ break;
+ if (!*s1)
+ return;
+ for (; s1 != s; s1--)
+ if (*(s1 - 1) == '\n')
+ break;
+ for (s2 = s1; *s2; s2++)
+ if (*s2 == '\n')
+ break;
+ if (*s2)
+ c = *s2, *s2 = '\000';
+ fprintf(stderr, "%s\n", s1);
+ if (c)
+ *s2 = c;
+}
--- /dev/null
+/* $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"
+#include "code.h"
+#include "tbl.h"
+
+long Ttime = 0;
+int Tstringoffset, Tcodeoffset, Tkvoffset;
+Tobj Ttrue, Tfalse;
+
+#define ISEQIK(ik, ko) \
+ (T_ISNUMBER (ko) && Tgetnumber (ko) == (ik))
+#define ISEQRK(rk, ko) \
+ (T_ISNUMBER (ko) && Tgetnumber (ko) == (rk))
+#define ISEQSK(sk, ko) \
+ (T_ISSTRING (ko) && Strcmp (((Tstring_t *) (ko))->s, (sk)) == 0)
+
+#define GETIKINDEX(tp, ik) (unsigned long) ik % tp->ln
+#define GETRKINDEX(tp, rk) (unsigned long) rk % tp->ln
+#define GETSKINDEX(tp, sk) (unsigned long) *sk % tp->ln
+
+typedef struct mapentry_t {
+ struct mapentry_t *next;
+ Tobj fmo, too;
+} mapentry_t;
+#define MAPENTRYSIZE sizeof (mapentry_t)
+#define MAPLISTN 100
+typedef struct map_tt {
+ struct mapentry_t *list[MAPLISTN];
+} map_tt;
+static map_tt map;
+static long mapentrybyte2size;
+
+static long truem, falsem;
+
+static Tinteger_t keyi;
+static Treal_t keyr;
+static Tstring_t keys;
+
+static void insert(Ttable_t *, Tobj, char *, Tobj);
+static Tobj find(Ttable_t *, Tobj, char *);
+static void delete(Ttable_t *, Tobj, char *);
+static void copytable(Ttable_t *, long);
+static void reccopytable(Ttable_t *, Ttable_t *);
+static void mapinit(void);
+static void mapterm(void);
+static void mapinsert(Tobj, Tobj);
+static Tobj mapfind(Tobj);
+
+void Tinit(void)
+{
+ Tstring_t s;
+ Tcode_t c;
+ Tkvlist_t kvl;
+
+ Mhaspointers[T_INTEGER] = FALSE;
+ Mhaspointers[T_REAL] = FALSE;
+ Mhaspointers[T_STRING] = FALSE;
+ Mhaspointers[T_CODE] = FALSE;
+ Mhaspointers[T_TABLE] = TRUE;
+ Ttrue = Tinteger(1);
+ truem = Mpushmark(Ttrue);
+ Tfalse = Tinteger(0);
+ falsem = Mpushmark(Tfalse);
+ Tstringoffset = (char *) &s.s[0] - (char *) &s + 1;
+ /* the + 1 above accounts for the null character */
+ Tcodeoffset = (char *) &c.c[0] - (char *) &c;
+ Tkvoffset = (char *) &kvl.kv[0] - (char *) &kvl;
+ keyi.head.type = T_INTEGER;
+ keyr.head.type = T_REAL;
+ keys.head.type = T_STRING;
+ mapentrybyte2size = M_BYTE2SIZE(MAPENTRYSIZE);
+}
+
+void Tterm(void)
+{
+ Mpopmark(falsem);
+ Tfalse = NULL;
+ Mpopmark(truem);
+ Ttrue = NULL;
+ Mdogc(M_GCFULL);
+ Mdogc(M_GCFULL);
+}
+
+void Tgchelper(void *p)
+{
+ Ttable_t *tp;
+ Tkvlist_t *kvlp;
+ long i, j;
+
+ /* must be a table */
+ tp = (Ttable_t *) p;
+ for (i = 0; i < tp->ln; i++)
+ if ((kvlp = tp->lp[i]))
+ for (j = 0; j < kvlp->i; j++)
+ Mmkcurr(kvlp->kv[j].ko), Mmkcurr(kvlp->kv[j].vo);
+}
+
+void Tfreehelper(void *p)
+{
+ Ttable_t *tp;
+ Tkvlist_t *kvlp;
+ long i;
+
+ /* must be a table */
+ tp = (Ttable_t *) p;
+ for (i = 0; i < tp->ln; i++)
+ if ((kvlp = tp->lp[i]))
+ Mfree(kvlp, M_BYTE2SIZE(T_KVLISTSIZE(kvlp->n)));
+ Mfree(tp->lp, M_BYTE2SIZE(tp->ln * T_KVLISTPTRSIZE));
+}
+
+Tobj Tinteger(long i)
+{
+ Tinteger_t *ip;
+
+ ip = Mnew(T_INTEGERSIZE, T_INTEGER);
+ ip->i = i;
+ return ip;
+}
+
+Tobj Treal(double d)
+{
+ Treal_t *rp;
+
+ if (d == (double) (long) d)
+ return Tinteger((long) d);
+ rp = Mnew(T_REALSIZE, T_REAL);
+ rp->d = d;
+ return rp;
+}
+
+Tobj Tstring(char *s)
+{
+ Tstring_t *sp;
+
+ sp = Mnew((long) T_STRINGSIZE(strlen(s)), T_STRING);
+ strcpy(&sp->s[0], s);
+ return sp;
+}
+
+Tobj Tcode(Code_t * cp, int ci, int cl)
+{
+ Tcode_t *codep;
+ Code_t *cp2;
+ char *s;
+ int i, j, cn;
+
+ codep = Mnew((long) T_CODESIZE(cl), T_CODE);
+ cp2 = codep->c;
+ for (i = 0; i < cl; i++) {
+ switch (cp[i].ctype) {
+ case C_INTEGER:
+ cp2[i] = cp[i];
+ if (cp2[i].next != C_NULL)
+ cp2[i].next -= ci;
+ break;
+ case C_REAL:
+ cp2[i] = cp[i];
+ if (cp2[i].next != C_NULL)
+ cp2[i].next -= ci;
+ break;
+ case C_STRING:
+ cp2[i] = cp[i];
+ if (cp2[i].next != C_NULL)
+ cp2[i].next -= ci;
+ s = (char *) &cp[i].u.s;
+ while (*s)
+ s++;
+ cn = (long) (s - (char *) &cp[i]) / sizeof(Code_t);
+ for (j = 0; j < cn; j++)
+ i++, cp2[i] = cp[i];
+ break;
+ default:
+ cp2[i] = cp[i];
+ if (cp2[i].next != C_NULL)
+ cp2[i].next -= ci;
+ if (cp2[i].u.fp != C_NULL)
+ cp2[i].u.fp -= ci;
+ break;
+ }
+ }
+ return codep;
+}
+
+Tobj Ttable(long sizehint)
+{
+ Ttable_t *tp;
+ Tkvlist_t **lp;
+ long i;
+
+ sizehint = (sizehint < 2) ? 2 : sizehint;
+ tp = Mnew(T_TABLESIZE, T_TABLE);
+ lp = Mallocate((long) (sizehint * T_KVLISTPTRSIZE));
+ tp->lp = lp;
+ tp->ln = sizehint;
+ tp->n = 0;
+ tp->time = Ttime;
+ for (i = 0; i < sizehint; i++)
+ lp[i] = NULL;
+ return tp;
+}
+
+
+void Tinsi(Tobj to, long ik, Tobj vo)
+{
+ long tm;
+
+ if (!to || !T_ISTABLE(to))
+ panic(POS, "Tinsi", "insert attempted on non-table");
+ tm = Mpushmark(to);
+ if (vo)
+ Mpushmark(vo);
+ keyi.i = ik;
+ insert(to, &keyi, NULL, vo);
+ Mpopmark(tm);
+}
+
+void Tinsr(Tobj to, double rk, Tobj vo)
+{
+ long tm;
+
+ if (!to || !T_ISTABLE(to))
+ panic(POS, "Tinsr", "insert attempted on non-table");
+ tm = Mpushmark(to);
+ if (vo)
+ Mpushmark(vo);
+ keyr.d = rk;
+ insert(to, &keyr, NULL, vo);
+ Mpopmark(tm);
+}
+
+void Tinss(Tobj to, char *sk, Tobj vo)
+{
+ long tm;
+
+ if (!to || !T_ISTABLE(to))
+ panic(POS, "Tinss", "insert attempted on non-table");
+ tm = Mpushmark(to);
+ if (vo)
+ Mpushmark(vo);
+ insert(to, &keys, sk, vo);
+ Mpopmark(tm);
+}
+
+void Tinso(Tobj to, Tobj ko, Tobj vo)
+{
+ long tm;
+
+ if (!to || !T_ISTABLE(to))
+ panic(POS, "Tinso", "insert attempted on non-table");
+ if (!ko || !(T_ISINTEGER(ko) || T_ISREAL(ko) || T_ISSTRING(ko)))
+ panic(POS, "Tinso", "bad key");
+ tm = Mpushmark(to);
+ Mpushmark(ko);
+ if (vo)
+ Mpushmark(vo);
+ insert(to, ko, NULL, vo);
+ Mpopmark(tm);
+}
+
+Tobj Tfindi(Tobj to, long ik)
+{
+ if (!to)
+ return NULL;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tfindi", "find attempted on non-table");
+ keyi.i = ik;
+ return find(to, &keyi, NULL);
+}
+
+Tobj Tfindr(Tobj to, double rk)
+{
+ if (!to)
+ return NULL;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tfindr", "find attempted on non-table");
+ keyr.d = rk;
+ return find(to, &keyr, NULL);
+}
+
+Tobj Tfinds(Tobj to, char *sk)
+{
+ if (!to)
+ return NULL;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tfinds", "find attempted on non-table");
+ return find(to, &keys, sk);
+}
+
+Tobj Tfindo(Tobj to, Tobj ko)
+{
+ if (!to || !ko)
+ return NULL;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tfindo", "find attempted on non-table");
+ if (!(T_ISINTEGER(ko) || T_ISREAL(ko) || T_ISSTRING(ko)))
+ panic(POS, "Tfindo", "bad key");
+ return find(to, ko, NULL);
+}
+
+void Tdeli(Tobj to, long ik)
+{
+ if (!to)
+ return;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tdeli", "delete attempted on non-table");
+ keyi.i = ik;
+ delete(to, &keyi, NULL);
+}
+
+void Tdelr(Tobj to, double rk)
+{
+ if (!to)
+ return;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tdelr", "delete attempted on non-table");
+ keyr.d = rk;
+ delete(to, &keyr, NULL);
+}
+
+void Tdels(Tobj to, char *sk)
+{
+ if (!to)
+ return;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tdels", "delete attempted on non-table");
+ delete(to, &keys, sk);
+}
+
+void Tdelo(Tobj to, Tobj ko)
+{
+ if (!to || !ko)
+ return;
+ if (!T_ISTABLE(to))
+ panic(POS, "Tdelo", "delete attempted on non-table");
+ if (!(T_ISINTEGER(ko) || T_ISREAL(ko) || T_ISSTRING(ko)))
+ panic(POS, "Tdelo", "bad key");
+ delete(to, ko, NULL);
+}
+
+Tobj Tcopy(Tobj fmvo)
+{
+ Tobj tovo;
+ long m;
+
+ switch (M_TYPEOF(fmvo)) {
+ case T_INTEGER:
+ case T_REAL:
+ case T_STRING:
+ case T_CODE:
+ tovo = fmvo;
+ break;
+ case T_TABLE:
+ mapinit();
+ m = Mpushmark(fmvo);
+ tovo = Mnew(T_TABLESIZE, T_TABLE);
+ mapinsert(fmvo, tovo);
+ reccopytable(fmvo, tovo);
+ Mpopmark(m);
+ mapterm();
+ break;
+ }
+ return tovo;
+}
+
+void Tgetfirst(Tobj to, Tkvindex_t * p)
+{
+ if (!to || !T_ISTABLE(to))
+ return;
+ p->tp = to, p->kvp = NULL, p->i = 0, p->j = 0;
+ for (; p->i < p->tp->ln; p->i++) {
+ if (!p->tp->lp[p->i])
+ continue;
+ for (; p->j < p->tp->lp[p->i]->i; p->j++) {
+ if ((p->kvp = &p->tp->lp[p->i]->kv[p->j]))
+ return;
+ }
+ p->j = 0;
+ }
+}
+
+void Tgetnext(Tkvindex_t * p)
+{
+ p->kvp = NULL;
+ p->j++;
+ for (; p->i < p->tp->ln; p->i++) {
+ if (!p->tp->lp[p->i])
+ continue;
+ for (; p->j < p->tp->lp[p->i]->i; p->j++) {
+ if ((p->kvp = &p->tp->lp[p->i]->kv[p->j]))
+ return;
+ }
+ p->j = 0;
+ }
+}
+
+static void insert(Ttable_t * tp, Tobj ko, char *sk, Tobj vo)
+{
+ Tkvlist_t *kvlp, *nkvlp;
+ Tkv_t *kvp;
+ Ttype_t kt;
+ long ik, i, ind, nln;
+ double rk;
+
+ switch ((kt = M_TYPEOF(ko))) {
+ case T_INTEGER:
+ ik = ((Tinteger_t *) ko)->i;
+ if ((kvlp = tp->lp[(ind = GETIKINDEX(tp, ik))]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQIK(ik, kvp[i].ko))
+ goto found;
+ break;
+ case T_REAL:
+ rk = ((Treal_t *) ko)->d;
+ if ((kvlp = tp->lp[(ind = GETRKINDEX(tp, rk))]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQRK(rk, kvp[i].ko))
+ goto found;
+ break;
+ case T_STRING:
+ if (M_AREAOF(ko) != 0)
+ sk = ((Tstring_t *) ko)->s;
+ if ((kvlp = tp->lp[(ind = GETSKINDEX(tp, sk))]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQSK(sk, kvp[i].ko))
+ goto found;
+ break;
+ }
+ if ((nln = tp->n + 1) > 4 * tp->ln && nln < SHRT_MAX) {
+ copytable(tp, nln);
+ switch (kt) {
+ case T_INTEGER:
+ ind = GETIKINDEX(tp, ik);
+ break;
+ case T_REAL:
+ ind = GETRKINDEX(tp, rk);
+ break;
+ case T_STRING:
+ ind = GETSKINDEX(tp, sk);
+ break;
+ }
+ kvlp = tp->lp[ind];
+ }
+ if (!kvlp) {
+ tp->lp[ind] = kvlp = Mallocate((long) T_KVLISTSIZE(1));
+ kvlp->i = 0, kvlp->n = 1;
+ } else if (kvlp->i == kvlp->n) {
+ tp->lp[ind] = nkvlp = Mallocate((long) T_KVLISTSIZE(kvlp->n * 2));
+ nkvlp->n = kvlp->n * 2;
+ for (i = 0; i < kvlp->n; i++)
+ nkvlp->kv[i] = kvlp->kv[i];
+ nkvlp->i = kvlp->i;
+ Mfree(kvlp, M_BYTE2SIZE(T_KVLISTSIZE(kvlp->n))), kvlp = nkvlp;
+ }
+ if (M_AREAOF(ko) == 0) { /* ko must be allocated */
+ switch (kt) {
+ case T_INTEGER:
+ ko = Tinteger(ik);
+ break;
+ case T_REAL:
+ ko = Treal(rk);
+ break;
+ case T_STRING:
+ ko = Tstring(sk);
+ break;
+ }
+ }
+
+ kvlp->kv[kvlp->i].ko = ko, kvlp->kv[kvlp->i++].vo = vo;
+ tp->n++;
+ tp->time = Ttime;
+ return;
+
+ found:
+ kvp[i].vo = vo;
+ tp->time = Ttime;
+}
+
+static Tobj find(Ttable_t * tp, Tobj ko, char *sk)
+{
+ Tkvlist_t *kvlp;
+ Tkv_t *kvp;
+ long ik, i;
+ double rk;
+
+ switch (M_TYPEOF(ko)) {
+ case T_INTEGER:
+ ik = ((Tinteger_t *) ko)->i;
+ if ((kvlp = tp->lp[GETIKINDEX(tp, ik)]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQIK(ik, kvp[i].ko))
+ goto found;
+ break;
+ case T_REAL:
+ rk = ((Treal_t *) ko)->d;
+ if ((kvlp = tp->lp[GETRKINDEX(tp, rk)]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQRK(rk, kvp[i].ko))
+ goto found;
+ break;
+ case T_STRING:
+ if (M_AREAOF(ko) != 0)
+ sk = ((Tstring_t *) ko)->s;
+ if ((kvlp = tp->lp[GETSKINDEX(tp, sk)]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQSK(sk, kvp[i].ko))
+ goto found;
+ break;
+ }
+ return NULL;
+
+ found:
+ return kvp[i].vo;
+}
+
+static void delete(Ttable_t * tp, Tobj ko, char *sk)
+{
+ Tkvlist_t *kvlp;
+ Tkv_t *kvp;
+ long ik, i, j;
+ double rk;
+
+ switch (M_TYPEOF(ko)) {
+ case T_INTEGER:
+ ik = ((Tinteger_t *) ko)->i;
+ if ((kvlp = tp->lp[GETIKINDEX(tp, ik)]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQIK(ik, kvp[i].ko))
+ goto found;
+ break;
+ case T_REAL:
+ rk = ((Treal_t *) ko)->d;
+ if ((kvlp = tp->lp[GETRKINDEX(tp, rk)]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQRK(rk, kvp[i].ko))
+ goto found;
+ break;
+ case T_STRING:
+ if (M_AREAOF(ko) != 0)
+ sk = ((Tstring_t *) ko)->s;
+ if ((kvlp = tp->lp[GETSKINDEX(tp, sk)]))
+ for (i = 0, kvp = &kvlp->kv[0]; i < kvlp->i; i++)
+ if (ISEQSK(sk, kvp[i].ko))
+ goto found;
+ break;
+ }
+ return;
+
+ found:
+ for (j = i, kvp = &kvlp->kv[0]; j < kvlp->i - 1; j++)
+ kvp[j] = kvp[j + 1];
+ kvlp->i--;
+ tp->n--;
+ tp->time = Ttime;
+}
+
+static void copytable(Ttable_t * tp, long ln)
+{
+ Tkvlist_t **olp, **lp;
+ Tkvlist_t *okvlp, *kvlp, *nkvlp;
+ Tkv_t *kvp;
+ long ik, oln, i, j, k, ind;
+ double rk;
+ char *sk;
+
+ lp = Mallocate((long) (ln * T_KVLISTPTRSIZE));
+ oln = tp->ln, tp->ln = ln;
+ olp = tp->lp, tp->lp = lp;
+ for (i = 0; i < ln; i++)
+ lp[i] = NULL;
+ for (i = 0; i < oln; i++) {
+ if (!(okvlp = olp[i]))
+ continue;
+ for (j = 0; j < okvlp->i; j++) {
+ kvp = &okvlp->kv[j];
+ switch (M_TYPEOF(kvp->ko)) {
+ case T_INTEGER:
+ ik = ((Tinteger_t *) kvp->ko)->i;
+ kvlp = lp[(ind = GETIKINDEX(tp, ik))];
+ break;
+ case T_REAL:
+ rk = ((Treal_t *) kvp->ko)->d;
+ kvlp = lp[(ind = GETRKINDEX(tp, rk))];
+ break;
+ case T_STRING:
+ sk = ((Tstring_t *) kvp->ko)->s;
+ kvlp = lp[(ind = GETSKINDEX(tp, sk))];
+ break;
+ }
+ if (!kvlp) {
+ lp[ind] = kvlp = Mallocate((long) T_KVLISTSIZE(1));
+ kvlp->i = 0, kvlp->n = 1;
+ } else if (kvlp->i == kvlp->n) {
+ lp[ind] = nkvlp =
+ Mallocate((long) T_KVLISTSIZE(kvlp->n * 2));
+ nkvlp->n = kvlp->n * 2;
+ for (k = 0; k < kvlp->i; k++)
+ nkvlp->kv[k] = kvlp->kv[k];
+ nkvlp->i = kvlp->i;
+ Mfree(kvlp, M_BYTE2SIZE(T_KVLISTSIZE(kvlp->n)));
+ kvlp = nkvlp;
+ }
+ kvlp->kv[kvlp->i].ko = kvp->ko, kvlp->kv[kvlp->i++].vo =
+ kvp->vo;
+ }
+ Mfree(okvlp, M_BYTE2SIZE(T_KVLISTSIZE(okvlp->n)));
+ }
+ Mfree(olp, M_BYTE2SIZE(oln * T_KVLISTPTRSIZE));
+}
+
+static void reccopytable(Ttable_t * fmtp, Ttable_t * totp)
+{
+ Tkv_t *fmkvp, *tokvp;
+ long i, j, m;
+
+ totp->lp = Mallocate((long) (fmtp->ln * T_KVLISTPTRSIZE));
+ totp->ln = fmtp->ln;
+ totp->n = fmtp->n;
+ totp->time = Ttime;
+ for (i = 0; i < totp->ln; i++) {
+ if (!fmtp->lp[i]) {
+ totp->lp[i] = NULL;
+ continue;
+ }
+ totp->lp[i] = Mallocate((long) T_KVLISTSIZE(fmtp->lp[i]->n));
+ totp->lp[i]->n = fmtp->lp[i]->n;
+ totp->lp[i]->i = 0;
+ }
+ m = Mpushmark(totp);
+ for (i = 0; i < totp->ln; i++) {
+ if (!totp->lp[i])
+ continue;
+ for (j = 0; j < fmtp->lp[i]->i; j++) {
+ fmkvp = &fmtp->lp[i]->kv[j], tokvp = &totp->lp[i]->kv[j];
+ tokvp->ko = fmkvp->ko;
+ switch (M_TYPEOF(fmkvp->vo)) {
+ case T_INTEGER:
+ case T_REAL:
+ case T_STRING:
+ case T_CODE:
+ tokvp->vo = fmkvp->vo;
+ break;
+ case T_TABLE:
+ if (!(tokvp->vo = mapfind(fmkvp->vo))) {
+ tokvp->vo = Mnew(T_TABLESIZE, T_TABLE);
+ mapinsert(fmkvp->vo, tokvp->vo);
+ reccopytable(fmkvp->vo, tokvp->vo);
+ }
+ break;
+ }
+ totp->lp[i]->i++;
+ }
+ }
+ Mpopmark(m);
+}
+
+static void mapinit(void)
+{
+ long li;
+
+ for (li = 0; li < MAPLISTN; li++)
+ map.list[li] = NULL;
+}
+
+static void mapterm(void)
+{
+ mapentry_t **lp;
+ mapentry_t *cep, *nep;
+ long li;
+
+ for (li = 0; li < MAPLISTN; li++) {
+ lp = &map.list[li];
+ for (cep = *lp; cep; cep = nep) {
+ nep = cep->next;
+ Mfree(cep, mapentrybyte2size);
+ }
+ *lp = NULL;
+ }
+}
+
+static void mapinsert(Tobj fmo, Tobj too)
+{
+ mapentry_t **lp;
+ mapentry_t *cep;
+
+ lp = &map.list[(unsigned long) fmo % MAPLISTN];
+ if (!(cep = Mallocate(MAPENTRYSIZE)))
+ panic(POS, "mapinsert", "cannot allocate mapentry");
+ cep->fmo = fmo, cep->too = too;
+ cep->next = *lp, *lp = cep;
+}
+
+static Tobj mapfind(Tobj fmo)
+{
+ mapentry_t **lp;
+ mapentry_t *cep;
+
+ lp = &map.list[(unsigned long) fmo % MAPLISTN];
+ for (cep = *lp; cep; cep = cep->next)
+ if (cep->fmo == fmo)
+ return cep->too;
+ return NULL;
+}
--- /dev/null
+/* $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 "code.h"
+#include "mem.h"
+
+Code_t *cbufp;
+int cbufn, cbufi;
+#define CBUFINCR 1000
+#define CBUFSIZE sizeof (Code_t)
+
+static int Cstringoffset;
+
+void Cinit(void)
+{
+ Code_t c;
+
+ cbufp = Marrayalloc((long) CBUFINCR * CBUFSIZE);
+ cbufn = CBUFINCR;
+ cbufi = 0;
+ Cstringoffset = (char *) &c.u.s[0] - (char *) &c + 1;
+ /* the + 1 above accounts for the null character */
+}
+
+void Cterm(void)
+{
+ Marrayfree(cbufp);
+ cbufp = NULL;
+ cbufn = cbufi = 0;
+}
+
+void Creset(void)
+{
+ cbufi = 0;
+}
+
+int Cnew(Ctype_t ctype)
+{
+ int i;
+
+ if (cbufi >= cbufn) {
+ cbufp = Marraygrow(cbufp, (long) (cbufn + CBUFINCR) * CBUFSIZE);
+ cbufn += CBUFINCR;
+ }
+ i = cbufi++;
+ cbufp[i].ctype = ctype;
+ cbufp[i].next = C_NULL;
+ return i;
+}
+
+int Cinteger(long i)
+{
+ int j;
+
+ if (cbufi >= cbufn) {
+ cbufp = Marraygrow(cbufp, (long) (cbufn + CBUFINCR) * CBUFSIZE);
+ cbufn += CBUFINCR;
+ }
+ j = cbufi++;
+ cbufp[j].ctype = C_INTEGER;
+ cbufp[j].u.i = i;
+ cbufp[j].next = C_NULL;
+ return j;
+}
+
+int Creal(double d)
+{
+ int i;
+
+ if (cbufi >= cbufn) {
+ cbufp = Marraygrow(cbufp, (long) (cbufn + CBUFINCR) * CBUFSIZE);
+ cbufn += CBUFINCR;
+ }
+ i = cbufi++;
+ cbufp[i].ctype = C_REAL;
+ cbufp[i].u.d = d;
+ cbufp[i].next = C_NULL;
+ return i;
+}
+
+int Cstring(char *s)
+{
+ int i, size, incr;
+
+ size = (strlen(s) + Cstringoffset + CBUFSIZE - 1) / CBUFSIZE;
+ if (cbufi + size > cbufn) {
+ incr = size > CBUFINCR ? size : CBUFINCR;
+ cbufp = Marraygrow(cbufp, (long) (cbufn + incr) * CBUFSIZE);
+ cbufn += incr;
+ }
+ i = cbufi, cbufi += size;
+ cbufp[i].ctype = C_STRING;
+ strcpy((char *) &cbufp[i].u.s[0], s);
+ cbufp[i].next = C_NULL;
+ return i;
+}
--- /dev/null
+/* $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 _CODE_H
+#define _CODE_H
+#define C_NULL -1
+
+#define C_ISSTMT(ct) (ct >= C_STMT && ct <= C_RETURN)
+
+ typedef enum {
+ C_CODE, C_ASSIGN, C_INTEGER, C_REAL, C_STRING, C_OR, C_AND,
+ C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_PLUS, C_MINUS, C_MUL,
+ C_DIV, C_MOD, C_UMINUS, C_NOT, C_PEXPR, C_FCALL, C_GVAR, C_LVAR,
+ C_PVAR, C_FUNCTION, C_TCONS, C_DECL, C_STMT, C_IF, C_WHILE,
+ C_FOR, C_FORIN, C_BREAK, C_CONTINUE, C_RETURN, C_INTERNAL,
+ C_ARGS, C_NOP, C_SIZE
+ } Ctype_t;
+
+ typedef struct Code_t {
+ Ctype_t ctype;
+ int next;
+ union {
+ char s[1];
+ double d;
+ long i;
+ int fp;
+ void *o;
+ } u;
+ } Code_t;
+#define C_CODESIZE sizeof (Code_t)
+
+#define Cgetstring(i) (char *) &cbufp[i].u.s[0]
+#define Cgetindex() cbufi
+
+#define Csettype(a, b) cbufp[a].ctype = b
+#define Csetfp(a, b) cbufp[a].u.fp = b
+#define Csetnext(a, b) cbufp[a].next = b
+#define Csetinteger(a, b) cbufp[a].u.i = b
+#define Csetobject(a, b) cbufp[a].u.o = b
+#define Csetreal(a, b) cbufp[a].u.d = b
+
+ extern Code_t *cbufp;
+ extern int cbufn, cbufi;
+
+ void Cinit(void);
+ void Cterm(void);
+ void Creset(void);
+ int Cnew(Ctype_t);
+ int Cinteger(long);
+ int Creal(double);
+ int Cstring(char *);
+#endif /* _CODE_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+colorname_t colornames[] = {
+{"aliceblue",240,248,255},
+{"antiquewhite",250,235,215},
+{"antiquewhite1",255,239,219},
+{"antiquewhite2",238,223,204},
+{"antiquewhite3",205,192,176},
+{"antiquewhite4",139,131,120},
+{"aquamarine",127,255,212},
+{"aquamarine1",127,255,212},
+{"aquamarine2",118,238,198},
+{"aquamarine3",102,205,170},
+{"aquamarine4",69,139,116},
+{"azure",240,255,255},
+{"azure1",240,255,255},
+{"azure2",224,238,238},
+{"azure3",193,205,205},
+{"azure4",131,139,139},
+{"beige",245,245,220},
+{"bisque",255,228,196},
+{"bisque1",255,228,196},
+{"bisque2",238,213,183},
+{"bisque3",205,183,158},
+{"bisque4",139,125,107},
+{"black",0,0,0},
+{"blanchedalmond",255,235,205},
+{"blue",0,0,255},
+{"blue1",0,0,255},
+{"blue2",0,0,238},
+{"blue3",0,0,205},
+{"blue4",0,0,139},
+{"blueviolet",138,43,226},
+{"brown",165,42,42},
+{"brown1",255,64,64},
+{"brown2",238,59,59},
+{"brown3",205,51,51},
+{"brown4",139,35,35},
+{"burlywood",222,184,135},
+{"burlywood1",255,211,155},
+{"burlywood2",238,197,145},
+{"burlywood3",205,170,125},
+{"burlywood4",139,115,85},
+{"cadetblue",95,158,160},
+{"cadetblue1",152,245,255},
+{"cadetblue2",142,229,238},
+{"cadetblue3",122,197,205},
+{"cadetblue4",83,134,139},
+{"chartreuse",127,255,0},
+{"chartreuse1",127,255,0},
+{"chartreuse2",118,238,0},
+{"chartreuse3",102,205,0},
+{"chartreuse4",69,139,0},
+{"chocolate",210,105,30},
+{"chocolate1",255,127,36},
+{"chocolate2",238,118,33},
+{"chocolate3",205,102,29},
+{"chocolate4",139,69,19},
+{"coral",255,127,80},
+{"coral1",255,114,86},
+{"coral2",238,106,80},
+{"coral3",205,91,69},
+{"coral4",139,62,47},
+{"cornflowerblue",100,149,237},
+{"cornsilk",255,248,220},
+{"cornsilk1",255,248,220},
+{"cornsilk2",238,232,205},
+{"cornsilk3",205,200,177},
+{"cornsilk4",139,136,120},
+{"crimson",220,20,60},
+{"cyan",0,255,255},
+{"cyan1",0,255,255},
+{"cyan2",0,238,238},
+{"cyan3",0,205,205},
+{"cyan4",0,139,139},
+{"darkgoldenrod",184,134,11},
+{"darkgoldenrod1",255,185,15},
+{"darkgoldenrod2",238,173,14},
+{"darkgoldenrod3",205,149,12},
+{"darkgoldenrod4",139,101,8},
+{"darkgreen",0,100,0},
+{"darkkhaki",189,183,107},
+{"darkolivegreen",85,107,47},
+{"darkolivegreen1",202,255,112},
+{"darkolivegreen2",188,238,104},
+{"darkolivegreen3",162,205,90},
+{"darkolivegreen4",110,139,61},
+{"darkorange",255,140,0},
+{"darkorange1",255,127,0},
+{"darkorange2",238,118,0},
+{"darkorange3",205,102,0},
+{"darkorange4",139,69,0},
+{"darkorchid",153,50,204},
+{"darkorchid1",191,62,255},
+{"darkorchid2",178,58,238},
+{"darkorchid3",154,50,205},
+{"darkorchid4",104,34,139},
+{"darksalmon",233,150,122},
+{"darkseagreen",143,188,143},
+{"darkseagreen1",193,255,193},
+{"darkseagreen2",180,238,180},
+{"darkseagreen3",155,205,155},
+{"darkseagreen4",105,139,105},
+{"darkslateblue",72,61,139},
+{"darkslategray",47,79,79},
+{"darkslategray1",151,255,255},
+{"darkslategray2",141,238,238},
+{"darkslategray3",121,205,205},
+{"darkslategray4",82,139,139},
+{"darkslategrey",47,79,79},
+{"darkturquoise",0,206,209},
+{"darkviolet",148,0,211},
+{"deeppink",255,20,147},
+{"deeppink1",255,20,147},
+{"deeppink2",238,18,137},
+{"deeppink3",205,16,118},
+{"deeppink4",139,10,80},
+{"deepskyblue",0,191,255},
+{"deepskyblue1",0,191,255},
+{"deepskyblue2",0,178,238},
+{"deepskyblue3",0,154,205},
+{"deepskyblue4",0,104,139},
+{"dimgray",105,105,105},
+{"dimgrey",105,105,105},
+{"dodgerblue",30,144,255},
+{"dodgerblue1",30,144,255},
+{"dodgerblue2",28,134,238},
+{"dodgerblue3",24,116,205},
+{"dodgerblue4",16,78,139},
+{"firebrick",178,34,34},
+{"firebrick1",255,48,48},
+{"firebrick2",238,44,44},
+{"firebrick3",205,38,38},
+{"firebrick4",139,26,26},
+{"floralwhite",255,250,240},
+{"forestgreen",34,139,34},
+{"gainsboro",220,220,220},
+{"ghostwhite",248,248,255},
+{"gold",255,215,0},
+{"gold1",255,215,0},
+{"gold2",238,201,0},
+{"gold3",205,173,0},
+{"gold4",139,117,0},
+{"goldenrod",218,165,32},
+{"goldenrod1",255,193,37},
+{"goldenrod2",238,180,34},
+{"goldenrod3",205,155,29},
+{"goldenrod4",139,105,20},
+{"gray",192,192,192},
+{"gray0",0,0,0},
+{"gray1",3,3,3},
+{"gray10",26,26,26},
+{"gray100",255,255,255},
+{"gray11",28,28,28},
+{"gray12",31,31,31},
+{"gray13",33,33,33},
+{"gray14",36,36,36},
+{"gray15",38,38,38},
+{"gray16",41,41,41},
+{"gray17",43,43,43},
+{"gray18",46,46,46},
+{"gray19",48,48,48},
+{"gray2",5,5,5},
+{"gray20",51,51,51},
+{"gray21",54,54,54},
+{"gray22",56,56,56},
+{"gray23",59,59,59},
+{"gray24",61,61,61},
+{"gray25",64,64,64},
+{"gray26",66,66,66},
+{"gray27",69,69,69},
+{"gray28",71,71,71},
+{"gray29",74,74,74},
+{"gray3",8,8,8},
+{"gray30",77,77,77},
+{"gray31",79,79,79},
+{"gray32",82,82,82},
+{"gray33",84,84,84},
+{"gray34",87,87,87},
+{"gray35",89,89,89},
+{"gray36",92,92,92},
+{"gray37",94,94,94},
+{"gray38",97,97,97},
+{"gray39",99,99,99},
+{"gray4",10,10,10},
+{"gray40",102,102,102},
+{"gray41",105,105,105},
+{"gray42",107,107,107},
+{"gray43",110,110,110},
+{"gray44",112,112,112},
+{"gray45",115,115,115},
+{"gray46",117,117,117},
+{"gray47",120,120,120},
+{"gray48",122,122,122},
+{"gray49",125,125,125},
+{"gray5",13,13,13},
+{"gray50",127,127,127},
+{"gray51",130,130,130},
+{"gray52",133,133,133},
+{"gray53",135,135,135},
+{"gray54",138,138,138},
+{"gray55",140,140,140},
+{"gray56",143,143,143},
+{"gray57",145,145,145},
+{"gray58",148,148,148},
+{"gray59",150,150,150},
+{"gray6",15,15,15},
+{"gray60",153,153,153},
+{"gray61",156,156,156},
+{"gray62",158,158,158},
+{"gray63",161,161,161},
+{"gray64",163,163,163},
+{"gray65",166,166,166},
+{"gray66",168,168,168},
+{"gray67",171,171,171},
+{"gray68",173,173,173},
+{"gray69",176,176,176},
+{"gray7",18,18,18},
+{"gray70",179,179,179},
+{"gray71",181,181,181},
+{"gray72",184,184,184},
+{"gray73",186,186,186},
+{"gray74",189,189,189},
+{"gray75",191,191,191},
+{"gray76",194,194,194},
+{"gray77",196,196,196},
+{"gray78",199,199,199},
+{"gray79",201,201,201},
+{"gray8",20,20,20},
+{"gray80",204,204,204},
+{"gray81",207,207,207},
+{"gray82",209,209,209},
+{"gray83",212,212,212},
+{"gray84",214,214,214},
+{"gray85",217,217,217},
+{"gray86",219,219,219},
+{"gray87",222,222,222},
+{"gray88",224,224,224},
+{"gray89",227,227,227},
+{"gray9",23,23,23},
+{"gray90",229,229,229},
+{"gray91",232,232,232},
+{"gray92",235,235,235},
+{"gray93",237,237,237},
+{"gray94",240,240,240},
+{"gray95",242,242,242},
+{"gray96",245,245,245},
+{"gray97",247,247,247},
+{"gray98",250,250,250},
+{"gray99",252,252,252},
+{"green",0,255,0},
+{"green1",0,255,0},
+{"green2",0,238,0},
+{"green3",0,205,0},
+{"green4",0,139,0},
+{"greenyellow",173,255,47},
+{"grey",192,192,192},
+{"grey0",0,0,0},
+{"grey1",3,3,3},
+{"grey10",26,26,26},
+{"grey100",255,255,255},
+{"grey11",28,28,28},
+{"grey12",31,31,31},
+{"grey13",33,33,33},
+{"grey14",36,36,36},
+{"grey15",38,38,38},
+{"grey16",41,41,41},
+{"grey17",43,43,43},
+{"grey18",46,46,46},
+{"grey19",48,48,48},
+{"grey2",5,5,5},
+{"grey20",51,51,51},
+{"grey21",54,54,54},
+{"grey22",56,56,56},
+{"grey23",59,59,59},
+{"grey24",61,61,61},
+{"grey25",64,64,64},
+{"grey26",66,66,66},
+{"grey27",69,69,69},
+{"grey28",71,71,71},
+{"grey29",74,74,74},
+{"grey3",8,8,8},
+{"grey30",77,77,77},
+{"grey31",79,79,79},
+{"grey32",82,82,82},
+{"grey33",84,84,84},
+{"grey34",87,87,87},
+{"grey35",89,89,89},
+{"grey36",92,92,92},
+{"grey37",94,94,94},
+{"grey38",97,97,97},
+{"grey39",99,99,99},
+{"grey4",10,10,10},
+{"grey40",102,102,102},
+{"grey41",105,105,105},
+{"grey42",107,107,107},
+{"grey43",110,110,110},
+{"grey44",112,112,112},
+{"grey45",115,115,115},
+{"grey46",117,117,117},
+{"grey47",120,120,120},
+{"grey48",122,122,122},
+{"grey49",125,125,125},
+{"grey5",13,13,13},
+{"grey50",127,127,127},
+{"grey51",130,130,130},
+{"grey52",133,133,133},
+{"grey53",135,135,135},
+{"grey54",138,138,138},
+{"grey55",140,140,140},
+{"grey56",143,143,143},
+{"grey57",145,145,145},
+{"grey58",148,148,148},
+{"grey59",150,150,150},
+{"grey6",15,15,15},
+{"grey60",153,153,153},
+{"grey61",156,156,156},
+{"grey62",158,158,158},
+{"grey63",161,161,161},
+{"grey64",163,163,163},
+{"grey65",166,166,166},
+{"grey66",168,168,168},
+{"grey67",171,171,171},
+{"grey68",173,173,173},
+{"grey69",176,176,176},
+{"grey7",18,18,18},
+{"grey70",179,179,179},
+{"grey71",181,181,181},
+{"grey72",184,184,184},
+{"grey73",186,186,186},
+{"grey74",189,189,189},
+{"grey75",191,191,191},
+{"grey76",194,194,194},
+{"grey77",196,196,196},
+{"grey78",199,199,199},
+{"grey79",201,201,201},
+{"grey8",20,20,20},
+{"grey80",204,204,204},
+{"grey81",207,207,207},
+{"grey82",209,209,209},
+{"grey83",212,212,212},
+{"grey84",214,214,214},
+{"grey85",217,217,217},
+{"grey86",219,219,219},
+{"grey87",222,222,222},
+{"grey88",224,224,224},
+{"grey89",227,227,227},
+{"grey9",23,23,23},
+{"grey90",229,229,229},
+{"grey91",232,232,232},
+{"grey92",235,235,235},
+{"grey93",237,237,237},
+{"grey94",240,240,240},
+{"grey95",242,242,242},
+{"grey96",245,245,245},
+{"grey97",247,247,247},
+{"grey98",250,250,250},
+{"grey99",252,252,252},
+{"honeydew",240,255,240},
+{"honeydew1",240,255,240},
+{"honeydew2",224,238,224},
+{"honeydew3",193,205,193},
+{"honeydew4",131,139,131},
+{"hotpink",255,105,180},
+{"hotpink1",255,110,180},
+{"hotpink2",238,106,167},
+{"hotpink3",205,96,144},
+{"hotpink4",139,58,98},
+{"indianred",205,92,92},
+{"indianred1",255,106,106},
+{"indianred2",238,99,99},
+{"indianred3",205,85,85},
+{"indianred4",139,58,58},
+{"indigo",75,0,130},
+{"ivory",255,255,240},
+{"ivory1",255,255,240},
+{"ivory2",238,238,224},
+{"ivory3",205,205,193},
+{"ivory4",139,139,131},
+{"khaki",240,230,140},
+{"khaki1",255,246,143},
+{"khaki2",238,230,133},
+{"khaki3",205,198,115},
+{"khaki4",139,134,78},
+{"lavender",230,230,250},
+{"lavenderblush",255,240,245},
+{"lavenderblush1",255,240,245},
+{"lavenderblush2",238,224,229},
+{"lavenderblush3",205,193,197},
+{"lavenderblush4",139,131,134},
+{"lawngreen",124,252,0},
+{"lemonchiffon",255,250,205},
+{"lemonchiffon1",255,250,205},
+{"lemonchiffon2",238,233,191},
+{"lemonchiffon3",205,201,165},
+{"lemonchiffon4",139,137,112},
+{"lightblue",173,216,230},
+{"lightblue1",191,239,255},
+{"lightblue2",178,223,238},
+{"lightblue3",154,192,205},
+{"lightblue4",104,131,139},
+{"lightcoral",240,128,128},
+{"lightcyan",224,255,255},
+{"lightcyan1",224,255,255},
+{"lightcyan2",209,238,238},
+{"lightcyan3",180,205,205},
+{"lightcyan4",122,139,139},
+{"lightgoldenrod",238,221,130},
+{"lightgoldenrod1",255,236,139},
+{"lightgoldenrod2",238,220,130},
+{"lightgoldenrod3",205,190,112},
+{"lightgoldenrod4",139,129,76},
+{"lightgoldenrodyellow",250,250,210},
+{"lightgray",211,211,211},
+{"lightgrey",211,211,211},
+{"lightpink",255,182,193},
+{"lightpink1",255,174,185},
+{"lightpink2",238,162,173},
+{"lightpink3",205,140,149},
+{"lightpink4",139,95,101},
+{"lightsalmon",255,160,122},
+{"lightsalmon1",255,160,122},
+{"lightsalmon2",238,149,114},
+{"lightsalmon3",205,129,98},
+{"lightsalmon4",139,87,66},
+{"lightseagreen",32,178,170},
+{"lightskyblue",135,206,250},
+{"lightskyblue1",176,226,255},
+{"lightskyblue2",164,211,238},
+{"lightskyblue3",141,182,205},
+{"lightskyblue4",96,123,139},
+{"lightslateblue",132,112,255},
+{"lightslategray",119,136,153},
+{"lightslategrey",119,136,153},
+{"lightsteelblue",176,196,222},
+{"lightsteelblue1",202,225,255},
+{"lightsteelblue2",188,210,238},
+{"lightsteelblue3",162,181,205},
+{"lightsteelblue4",110,123,139},
+{"lightyellow",255,255,224},
+{"lightyellow1",255,255,224},
+{"lightyellow2",238,238,209},
+{"lightyellow3",205,205,180},
+{"lightyellow4",139,139,122},
+{"limegreen",50,205,50},
+{"linen",250,240,230},
+{"magenta",255,0,255},
+{"magenta1",255,0,255},
+{"magenta2",238,0,238},
+{"magenta3",205,0,205},
+{"magenta4",139,0,139},
+{"maroon",176,48,96},
+{"maroon1",255,52,179},
+{"maroon2",238,48,167},
+{"maroon3",205,41,144},
+{"maroon4",139,28,98},
+{"mediumaquamarine",102,205,170},
+{"mediumblue",0,0,205},
+{"mediumorchid",186,85,211},
+{"mediumorchid1",224,102,255},
+{"mediumorchid2",209,95,238},
+{"mediumorchid3",180,82,205},
+{"mediumorchid4",122,55,139},
+{"mediumpurple",147,112,219},
+{"mediumpurple1",171,130,255},
+{"mediumpurple2",159,121,238},
+{"mediumpurple3",137,104,205},
+{"mediumpurple4",93,71,139},
+{"mediumseagreen",60,179,113},
+{"mediumslateblue",123,104,238},
+{"mediumspringgreen",0,250,154},
+{"mediumturquoise",72,209,204},
+{"mediumvioletred",199,21,133},
+{"midnightblue",25,25,112},
+{"mintcream",245,255,250},
+{"mistyrose",255,228,225},
+{"mistyrose1",255,228,225},
+{"mistyrose2",238,213,210},
+{"mistyrose3",205,183,181},
+{"mistyrose4",139,125,123},
+{"moccasin",255,228,181},
+{"navajowhite",255,222,173},
+{"navajowhite1",255,222,173},
+{"navajowhite2",238,207,161},
+{"navajowhite3",205,179,139},
+{"navajowhite4",139,121,94},
+{"navy",0,0,128},
+{"navyblue",0,0,128},
+{"oldlace",253,245,230},
+{"olivedrab",107,142,35},
+{"olivedrab1",192,255,62},
+{"olivedrab2",179,238,58},
+{"olivedrab3",154,205,50},
+{"olivedrab4",105,139,34},
+{"orange",255,165,0},
+{"orange1",255,165,0},
+{"orange2",238,154,0},
+{"orange3",205,133,0},
+{"orange4",139,90,0},
+{"orangered",255,69,0},
+{"orangered1",255,69,0},
+{"orangered2",238,64,0},
+{"orangered3",205,55,0},
+{"orangered4",139,37,0},
+{"orchid",218,112,214},
+{"orchid1",255,131,250},
+{"orchid2",238,122,233},
+{"orchid3",205,105,201},
+{"orchid4",139,71,137},
+{"palegoldenrod",238,232,170},
+{"palegreen",152,251,152},
+{"palegreen1",154,255,154},
+{"palegreen2",144,238,144},
+{"palegreen3",124,205,124},
+{"palegreen4",84,139,84},
+{"paleturquoise",175,238,238},
+{"paleturquoise1",187,255,255},
+{"paleturquoise2",174,238,238},
+{"paleturquoise3",150,205,205},
+{"paleturquoise4",102,139,139},
+{"palevioletred",219,112,147},
+{"palevioletred1",255,130,171},
+{"palevioletred2",238,121,159},
+{"palevioletred3",205,104,137},
+{"palevioletred4",139,71,93},
+{"papayawhip",255,239,213},
+{"peachpuff",255,218,185},
+{"peachpuff1",255,218,185},
+{"peachpuff2",238,203,173},
+{"peachpuff3",205,175,149},
+{"peachpuff4",139,119,101},
+{"peru",205,133,63},
+{"pink",255,192,203},
+{"pink1",255,181,197},
+{"pink2",238,169,184},
+{"pink3",205,145,158},
+{"pink4",139,99,108},
+{"plum",221,160,221},
+{"plum1",255,187,255},
+{"plum2",238,174,238},
+{"plum3",205,150,205},
+{"plum4",139,102,139},
+{"powderblue",176,224,230},
+{"purple",160,32,240},
+{"purple1",155,48,255},
+{"purple2",145,44,238},
+{"purple3",125,38,205},
+{"purple4",85,26,139},
+{"red",255,0,0},
+{"red1",255,0,0},
+{"red2",238,0,0},
+{"red3",205,0,0},
+{"red4",139,0,0},
+{"rosybrown",188,143,143},
+{"rosybrown1",255,193,193},
+{"rosybrown2",238,180,180},
+{"rosybrown3",205,155,155},
+{"rosybrown4",139,105,105},
+{"royalblue",65,105,225},
+{"royalblue1",72,118,255},
+{"royalblue2",67,110,238},
+{"royalblue3",58,95,205},
+{"royalblue4",39,64,139},
+{"saddlebrown",139,69,19},
+{"salmon",250,128,114},
+{"salmon1",255,140,105},
+{"salmon2",238,130,98},
+{"salmon3",205,112,84},
+{"salmon4",139,76,57},
+{"sandybrown",244,164,96},
+{"seagreen",46,139,87},
+{"seagreen1",84,255,159},
+{"seagreen2",78,238,148},
+{"seagreen3",67,205,128},
+{"seagreen4",46,139,87},
+{"seashell",255,245,238},
+{"seashell1",255,245,238},
+{"seashell2",238,229,222},
+{"seashell3",205,197,191},
+{"seashell4",139,134,130},
+{"sienna",160,82,45},
+{"sienna1",255,130,71},
+{"sienna2",238,121,66},
+{"sienna3",205,104,57},
+{"sienna4",139,71,38},
+{"skyblue",135,206,235},
+{"skyblue1",135,206,255},
+{"skyblue2",126,192,238},
+{"skyblue3",108,166,205},
+{"skyblue4",74,112,139},
+{"slateblue",106,90,205},
+{"slateblue1",131,111,255},
+{"slateblue2",122,103,238},
+{"slateblue3",105,89,205},
+{"slateblue4",71,60,139},
+{"slategray",112,128,144},
+{"slategray1",198,226,255},
+{"slategray2",185,211,238},
+{"slategray3",159,182,205},
+{"slategray4",108,123,139},
+{"slategrey",112,128,144},
+{"snow",255,250,250},
+{"snow1",255,250,250},
+{"snow2",238,233,233},
+{"snow3",205,201,201},
+{"snow4",139,137,137},
+{"springgreen",0,255,127},
+{"springgreen1",0,255,127},
+{"springgreen2",0,238,118},
+{"springgreen3",0,205,102},
+{"springgreen4",0,139,69},
+{"steelblue",70,130,180},
+{"steelblue1",99,184,255},
+{"steelblue2",92,172,238},
+{"steelblue3",79,148,205},
+{"steelblue4",54,100,139},
+{"tan",210,180,140},
+{"tan1",255,165,79},
+{"tan2",238,154,73},
+{"tan3",205,133,63},
+{"tan4",139,90,43},
+{"thistle",216,191,216},
+{"thistle1",255,225,255},
+{"thistle2",238,210,238},
+{"thistle3",205,181,205},
+{"thistle4",139,123,139},
+{"tomato",255,99,71},
+{"tomato1",255,99,71},
+{"tomato2",238,92,66},
+{"tomato3",205,79,57},
+{"tomato4",139,54,38},
+{"turquoise",64,224,208},
+{"turquoise1",0,245,255},
+{"turquoise2",0,229,238},
+{"turquoise3",0,197,205},
+{"turquoise4",0,134,139},
+{"violet",238,130,238},
+{"violetred",208,32,144},
+{"violetred1",255,62,150},
+{"violetred2",238,58,140},
+{"violetred3",205,50,120},
+{"violetred4",139,34,82},
+{"wheat",245,222,179},
+{"wheat1",255,231,186},
+{"wheat2",238,216,174},
+{"wheat3",205,186,150},
+{"wheat4",139,126,102},
+{"white",255,255,255},
+{"whitesmoke",245,245,245},
+{"yellow",255,255,0},
+{"yellow1",255,255,0},
+{"yellow2",238,238,0},
+{"yellow3",205,205,0},
+{"yellow4",139,139,0},
+{"yellowgreen",154,205,50},
+};
--- /dev/null
+/* $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"
+
+int warnflag;
+char *leftypath, *leftyoptions, *shellpath;
+jmp_buf exitljbuf;
+int idlerunmode;
+fd_set inputfds;
+#ifdef FEATURE_NETSCAPE
+static int innetscape;
+static char *nswin;
+#endif
+
+#ifndef FEATURE_MS
+#define PATHDEL '/'
+#define PATHSEP ':'
+#define PATHSEPSTR ":"
+#define PATHLEFTY "/../lib/lefty"
+#else
+#define PATHDEL '\\'
+#define PATHSEP ';'
+#define PATHSEPSTR ";"
+#define PATHLEFTY "\\..\\lib\\lefty"
+#endif
+#ifdef FEATURE_X11
+#define WINSYS "LEFTYWINSYS=X11"
+#endif
+#ifdef FEATURE_MS
+#define WINSYS "LEFTYWINSYS=mswin"
+#endif
+#ifdef FEATURE_GTK
+#ifdef FEATURE_MS
+#define WINSYS "LEFTYWINSYS=mswin"
+#else
+#define WINSYS "LEFTYWINSYS=X11"
+#endif
+#endif
+#include "g.h"
+#include "gcommon.h"
+
+#ifdef FEATURE_GTK
+static int Gnocallbacks;
+#else
+#ifdef FEATURE_MS
+extern int Gnocallbacks;
+/* #else */
+/* static int Gnocallbacks; */
+#endif
+#endif
+
+static char *pathp;
+#define PATHINCR 10240
+#define PATHSIZE sizeof (char)
+static char *cmdp;
+#define CMDINCR 4096
+#define CMDSIZE sizeof (char)
+
+static char *lpathp;
+
+int init(char *aout)
+{
+ char *s1, *s2, c = 0;
+ int k;
+#ifdef FEATURE_WIN32
+#ifndef FEATURE_GTK
+ extern HANDLE hinstance;
+ char buf[260];
+#endif
+#endif
+
+#ifdef FEATURE_NETSCAPE
+ if (getenv("INNETSCAPE"))
+ innetscape = TRUE, nswin = getenv("NSWIN");
+#endif
+ if (!(pathp = malloc(PATHINCR * PATHSIZE)))
+ panic(POS, "init", "pathp malloc failed");
+ if (!(cmdp = malloc(CMDINCR * CMDSIZE)))
+ panic(POS, "init", "cmdp malloc failed");
+ shellpath = getenv("PATH");
+#if defined(FEATURE_GTK) || defined(FEATURE_X11)
+ if (!strchr(aout, PATHDEL)) {
+ leftypath = "";
+ if ((s1 = buildpath(aout, TRUE)))
+ aout = strdup(s1);
+ } else
+ aout = strdup(aout);
+#else
+ GetModuleFileName(hinstance, buf, 260);
+ aout = buf;
+#endif
+ if (!(s1 = strrchr(aout, PATHDEL)))
+ s1 = aout;
+ *s1 = 0;
+ if (!(leftypath = malloc(PATHINCR * PATHSIZE)))
+ panic(POS, "init", "leftypath malloc failed");
+ leftypath[0] = 0;
+ if ((s1 = getenv("LEFTYPATH")))
+ strcat(leftypath, s1), strcat(leftypath, PATHSEPSTR);
+ if (*aout)
+ strcat(leftypath, aout), strcat(leftypath, PATHSEPSTR);
+ for (k = 0; k < 2; k++) {
+ if (k == 0)
+ s1 = aout;
+ else
+ s1 = shellpath;
+ while (s1) {
+ if ((s2 = strchr(s1, PATHSEP)))
+ c = *s2, *s2 = 0;
+ strcat(leftypath, s1);
+ strcat(leftypath, PATHLEFTY);
+ if (s2) {
+ *s2 = c, s1 = s2 + 1;
+ strcat(leftypath, PATHSEPSTR);
+ } else
+ s1 = NULL;
+ }
+ if (leftypath[0])
+ strcat(leftypath, PATHSEPSTR);
+ }
+#ifdef LEFTYPATH
+ strcat(leftypath, LEFTYPATH), strcat(leftypath, PATHSEPSTR);
+#endif
+ if (!(leftyoptions = getenv("LEFTYOPTIONS")))
+ leftyoptions = "";
+ putenv(WINSYS);
+ return 0;
+}
+
+void term(void)
+{
+ if (lpathp)
+ free(lpathp);
+ if (pathp)
+ free(pathp);
+ if (cmdp)
+ free(cmdp);
+}
+
+/* given a file name, it looks for this file in LEFTYPATH
+ (and if flag == TRUE in PATH)
+
+ returns the first occurance of that file or NULL
+*/
+char *buildpath(char *file, int flag)
+{
+ struct stat statbuf;
+ char *s1, *s2;
+ int mode, pathi, i;
+
+#ifdef FEATURE_NETSCAPE
+ if (flag == FALSE && innetscape) {
+#ifdef FEATURE_WIN32
+ HWND hwnd;
+ char *s;
+
+ if (!nswin) {
+ MessageBox((HWND) NULL, "error: no peer window",
+ "Lefty Warning", MB_APPLMODAL);
+ return NULL;
+ }
+ hwnd = atol(nswin);
+ fprintf(stdout, "file %s\n", file);
+ if (fflush(stdout) == -1) {
+ MessageBox((HWND) NULL, "Lost Connection to Netscape",
+ "Lefty Warning", MB_APPLMODAL);
+ return NULL;
+ }
+ SendMessage(hwnd, WM_USER, 12, 34);
+ fgets(pathp, PATHINCR - 1, stdin);
+ pathp[strlen(pathp) - 1] = 0;
+ if (pathp[0] == 0)
+ return NULL;
+ return pathp;
+#else
+ Window window;
+ static XButtonEvent ev;
+
+ if (!nswin) {
+ fprintf(stderr, "error: no peer window\n");
+ return NULL;
+ }
+ window = strtol(nswin, NULL, 16);
+ fprintf(stdout, "file %s\n", file);
+ if (fflush(stdout) == -1) {
+ fprintf(stderr, "Lost Connection to Netscape\n");
+ return NULL;
+ }
+ ev.type = ButtonPress;
+ ev.window = window;
+ ev.x = -123, ev.y = -123;
+ XSendEvent(Gdisplay, window, False, 0, (XEvent *) & ev);
+ XFlush(Gdisplay);
+ fgets(pathp, PATHINCR - 1, stdin);
+ pathp[strlen(pathp) - 1] = 0;
+ if (pathp[0] == 0)
+ return NULL;
+ return pathp;
+#endif
+ }
+#endif
+
+#ifndef FEATURE_MS
+ if (file && file[0] && strchr(file, PATHDEL))
+ return file;
+ mode = S_IRUSR | (flag ? S_IXUSR : 0);
+ for (i = 0; i < 2; i++) {
+ if (i == 0)
+ s1 = leftypath;
+ else
+ s1 = shellpath;
+ while (*s1) {
+ pathi = 0;
+ while (*s1 && *s1 != PATHSEP)
+ if (pathi < PATHINCR)
+ pathp[pathi++] = *s1++;
+ if (*s1)
+ s1++;
+ if (pathi + 3 + strlen(file) >= PATHINCR)
+ continue;
+ pathp[pathi++] = PATHDEL;
+ for (s2 = file; *s2; s2++)
+ pathp[pathi++] = *s2;
+ pathp[pathi] = '\000';
+ if (stat(pathp, &statbuf) == 0 && (statbuf.st_mode & mode))
+ return pathp;
+ }
+ }
+#else
+ if (file && file[0] && strchr(file, PATHDEL))
+ return file;
+ mode = ~0;
+ for (i = 0; i < 2; i++) {
+ if (i == 0)
+ s1 = leftypath;
+ else
+ s1 = shellpath;
+ while (*s1) {
+ pathi = 0;
+ while (*s1 && *s1 != PATHSEP)
+ if (pathi < PATHINCR)
+ pathp[pathi++] = *s1++;
+ if (*s1)
+ s1++;
+ if (pathi + 7 + strlen(file) >= PATHINCR)
+ continue;
+ pathp[pathi++] = PATHDEL;
+ for (s2 = file; *s2; s2++)
+ pathp[pathi++] = *s2;
+ if (flag) {
+ pathp[pathi++] = '.';
+ pathp[pathi++] = 'e';
+ pathp[pathi++] = 'x';
+ pathp[pathi++] = 'e';
+ }
+ pathp[pathi] = '\000';
+ if (stat(pathp, &statbuf) == 0 && (statbuf.st_mode & mode))
+ return pathp;
+ }
+ }
+#endif
+ return NULL;
+}
+
+/* given a file name (path) and an optional format (fmt)
+ it builds a shell command.
+
+ %e is replaced by the command path
+ %i ... the input channel descriptor
+ %o ... the output channel descriptor
+ %h ... the hostname
+
+ returns the complete command string or NULL
+*/
+char *buildcommand(char *path, char *host, int infd, int outfd, char *fmt)
+{
+ char buf[10];
+ char *s1, *s2;
+ int bufi;
+
+ cmdp[0] = '\000';
+ for (bufi = 0, s1 = fmt; *s1; s1++) {
+ if (*s1 == '%') {
+ if (*(s1 + 1) == 'e') {
+ s1++;
+ if (bufi + strlen(path) >= CMDINCR)
+ return NULL;
+ for (s2 = path; *s2; s2++)
+ cmdp[bufi++] = *s2;
+ continue;
+ } else if (*(s1 + 1) == 'i') {
+ if (infd == -1)
+ buf[0] = '%', buf[1] = 'd', buf[2] = '\000';
+ else
+ sprintf(buf, "%d", infd);
+ s1++;
+ if (bufi + strlen(buf) >= CMDINCR)
+ return NULL;
+ for (s2 = buf; *s2; s2++)
+ cmdp[bufi++] = *s2;
+ continue;
+ } else if (*(s1 + 1) == 'o') {
+ if (outfd == -1)
+ buf[0] = '%', buf[1] = 'd', buf[2] = '\000';
+ else
+ sprintf(buf, "%d", outfd);
+ s1++;
+ if (bufi + strlen(buf) >= CMDINCR)
+ return NULL;
+ for (s2 = buf; *s2; s2++)
+ cmdp[bufi++] = *s2;
+ continue;
+ } else if (*(s1 + 1) == 'h') {
+ s1++;
+ if (bufi + strlen(host) >= CMDINCR)
+ return NULL;
+ for (s2 = host; *s2; s2++)
+ cmdp[bufi++] = *s2;
+ continue;
+ }
+ }
+ if (bufi + 1 >= CMDINCR)
+ return NULL;
+ cmdp[bufi++] = *s1;
+ }
+ if (bufi + 1 >= CMDINCR)
+ return NULL;
+ cmdp[bufi] = '\000';
+ return &cmdp[0];
+}
+
+/* varargs function for printing a warning */
+void warning(char *file, int line, char *func, char *fmt, ...)
+{
+ va_list args;
+
+#ifndef FEATURE_MS
+ if (!warnflag)
+ return;
+
+ va_start(args, fmt);
+ /* Gnocallbacks = TRUE; */
+ fprintf(stderr, "warning: (file %s, line %d, func %s) ", file, line,
+ func);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ /* Gnocallbacks = FALSE; */
+ va_end(args);
+#else
+ char buf[256];
+
+ if (!warnflag)
+ return;
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ Gnocallbacks = TRUE;
+ MessageBox((HWND) NULL, buf, "Lefty Warning", MB_APPLMODAL);
+ Gnocallbacks = FALSE;
+ va_end(args);
+#endif
+}
+
+/* varargs function for printing an error message and aborting */
+void panic(char *file, int line, char *func, char *fmt, ...)
+{
+ va_list args;
+
+#ifndef FEATURE_MS
+ va_start(args, fmt);
+ /* Gnocallbacks = TRUE; */
+ fprintf(stderr, "panic: (file %s, line %d, func %s) ", file, line,
+ func);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ fflush(stdout);
+ /* Gnocallbacks = FALSE; */
+ va_end(args);
+#else
+ char buf[256];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ Gnocallbacks = TRUE;
+ MessageBox((HWND) NULL, buf, "Lefty PANIC", MB_APPLMODAL);
+ Gnocallbacks = FALSE;
+ va_end(args);
+#endif
+ abort();
+}
+
+/* varargs function for printing an error message, and the
+ error message corresponding to errno and aborting
+*/
+void panic2(char *file, int line, char *func, char *fmt, ...)
+{
+ va_list args;
+
+#ifndef FEATURE_MS
+ va_start(args, fmt);
+ /* Gnocallbacks = TRUE; */
+ fprintf(stderr, "panic: (file %s, line %d, func %s) ", file, line,
+ func);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ perror("");
+ fflush(stdout);
+ /* Gnocallbacks = FALSE; */
+ va_end(args);
+#else
+ char buf[256];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ Gnocallbacks = TRUE;
+ MessageBox((HWND) NULL, buf, "Lefty PANIC", MB_APPLMODAL);
+ Gnocallbacks = FALSE;
+ va_end(args);
+#endif
+ abort();
+}
+
+#ifdef FEATURE_MS
+int printf(const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+ int l;
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ l = strlen(buf);
+ if (l > 0) {
+ if (buf[l - 1] == '\n')
+ buf[l - 1] = 0;
+ }
+ if (buf[0]) {
+ Gnocallbacks = TRUE;
+ MessageBox((HWND) NULL, buf, "Lefty printf", MB_APPLMODAL);
+ Gnocallbacks = FALSE;
+ }
+ va_end(args);
+ return l;
+}
+#endif
--- /dev/null
+/* $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 _COMMON_H
+#define _COMMON_H
+
+/* some config and conversion definitions from graphviz distribution */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef MSWIN32
+#define FEATURE_WIN32
+#define FEATURE_MS
+#else
+#ifndef FEATURE_GTK
+#define FEATURE_X11
+#endif
+#endif
+#ifdef HAVECS
+#define FEATURE_CS
+#endif
+#ifdef HAVENETSCAPE
+#define FEATURE_NETSCAPE
+#endif
+#ifdef HAVEGMAP
+#define FEATURE_GMAP
+#define FEATURE_MINTSIZE
+#endif
+#ifdef HAVEDOT
+#define FEATURE_DOT
+#endif
+#ifdef GNU
+#define FEATURE_GNU
+#endif
+#ifdef HAVERUSAGE
+#define FEATURE_RUSAGE
+#endif
+/* */
+
+#ifdef FEATURE_CS
+#include <ast.h>
+#else
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#endif
+
+#include <math.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <ctype.h>
+
+#ifdef FEATURE_WIN32
+#include <windows.h>
+#include <commdlg.h>
+#endif
+#ifdef FEATURE_MS
+#include <malloc.h>
+#endif
+
+#define POS __FILE__, __LINE__
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifndef L_SUCCESS
+#define L_SUCCESS 1
+#define L_FAILURE 0
+#endif
+
+#define CHARSRC 0
+#define FILESRC 1
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef REALSTRCMP
+#define Strcmp(s1, s2) ( \
+ *(s1) == *(s2) ? ( \
+ (*s1) ? strcmp ((s1) + 1, (s2) + 1) : 0 \
+ ) : (*(s1) < *(s2) ? -1 : 1) \
+)
+#else
+#define Strcmp(s1, s2) strcmp ((s1), (s2))
+#endif
+
+ extern int warnflag;
+ extern char *leftypath, *leftyoptions, *shellpath;
+ extern jmp_buf exitljbuf;
+ extern int idlerunmode;
+ extern fd_set inputfds;
+
+ int init(char *);
+ void term(void);
+ char *buildpath(char *, int);
+ char *buildcommand(char *, char *, int, int, char *);
+ void warning(char *, int, char *, char *, ...);
+ void panic(char *, int, char *, char *, ...);
+ void panic2(char *, int, char *, char *, ...);
+#endif /* _COMMON_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* $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"
+#include "code.h"
+#include "tbl.h"
+#include "str.h"
+#include "display.h"
+
+typedef struct dnode_t {
+ Ttype_t ttype;
+ Tobj ko, vo;
+ char *path;
+} dnode_t;
+
+typedef struct seennode_t {
+ Tobj vo;
+ char *path;
+} seennode_t;
+static seennode_t *seenp;
+static int seeni, seenn;
+#define SEENINCR 100
+#define SEENSIZE sizeof (seennode_t)
+
+static int indent, afternl;
+
+static void update(dnode_t *);
+static int cmp(const void *, const void *);
+static seennode_t *findseen(dnode_t *);
+static void add2seen(dnode_t *);
+static void pr(char *);
+
+void Dinit(void)
+{
+ seenp = Marrayalloc((long) SEENINCR * SEENSIZE);
+ seeni = 0;
+ seenn = SEENINCR;
+}
+
+void Dterm(void)
+{
+ Marrayfree(seenp);
+ seeni = seenn = 0;
+}
+
+void Dtrace(Tobj to, int offset)
+{
+ dnode_t dnode;
+ char *s;
+ int i;
+
+ indent = offset - 2;
+ afternl = TRUE;
+ if (Tgettype(to) != T_TABLE) {
+ pr((s = Ssfull(NULL, to))), free(s);
+ return;
+ }
+
+ seeni = 0;
+ dnode.vo = to;
+ dnode.path = "";
+ update(&dnode);
+ for (i = 0; i < seeni; i++)
+ free(seenp[i].path), seenp[i].path = NULL;
+}
+
+static void update(dnode_t * pnode)
+{
+ Tkvindex_t tkvi;
+ dnode_t *list, *cnode;
+ seennode_t *seennode;
+ char *s;
+ long i, n;
+
+ indent += 2;
+ n = ((Ttable_t *) pnode->vo)->n;
+ if (!(list = malloc(n * sizeof(dnode_t))))
+ panic(POS, "update", "list malloc failed");
+ for (cnode = &list[0], Tgetfirst(pnode->vo, &tkvi); tkvi.kvp;
+ cnode++, Tgetnext(&tkvi)) {
+ cnode->ko = tkvi.kvp->ko;
+ cnode->vo = tkvi.kvp->vo;
+ cnode->ttype = Tgettype(cnode->vo);
+ }
+ qsort((char *) list, n, sizeof(dnode_t), cmp);
+ for (i = 0, cnode = &list[0]; i < n; i++, cnode++) {
+ cnode->path = Spath(pnode->path, cnode->ko);
+ seennode = findseen(cnode);
+ if (seennode) {
+ pr((s = Sseen(cnode->ko, seennode->path))), free(s);
+ } else {
+ add2seen(cnode);
+ if (cnode->ttype == T_TABLE) {
+ pr((s = Stfull(cnode->ko))), free(s);
+ update(cnode);
+ pr("];");
+ } else {
+ pr((s = Ssfull(cnode->ko, cnode->vo))), free(s);
+ }
+ }
+ }
+ free(list);
+ indent -= 2;
+}
+
+static int cmp(const void *a, const void *b)
+{
+ Ttype_t atype, btype;
+ dnode_t *anode, *bnode;
+ double d1 = 0.0, d2 = 0.0;
+
+ anode = (dnode_t *) a, bnode = (dnode_t *) b;
+ atype = Tgettype(anode->ko), btype = Tgettype(bnode->ko);
+ if (atype != btype)
+ return (atype - btype);
+ if (atype == T_STRING)
+ return Strcmp(Tgetstring(anode->ko), Tgetstring(bnode->ko));
+ if (atype == T_INTEGER)
+ d1 = Tgetinteger(anode->ko), d2 = Tgetinteger(bnode->ko);
+ else if (atype == T_REAL)
+ d1 = Tgetreal(anode->ko), d2 = Tgetreal(bnode->ko);
+ if (d1 < d2)
+ return -1;
+ else if (d1 > d2)
+ return 1;
+ else
+ return 0; /* but this should never happen since keys are unique */
+}
+
+static seennode_t *findseen(dnode_t * cnode)
+{
+ int i;
+
+ for (i = 0; i < seeni; i++)
+ if (seenp[i].vo == cnode->vo)
+ return &seenp[i];
+ return NULL;
+}
+
+static void add2seen(dnode_t * cnode)
+{
+ if (seeni >= seenn) {
+ seenp = Marraygrow(seenp, (long) (seenn + SEENINCR) * SEENSIZE);
+ seenn += SEENINCR;
+ }
+ seenp[seeni].vo = cnode->vo;
+ seenp[seeni++].path = cnode->path;
+}
+
+static void pr(char *s)
+{
+ char *s1;
+ int i;
+
+ for (s1 = s; *s1; s1++) {
+ if (afternl) {
+ for (i = 0; i < indent; i++)
+ putchar(' ');
+ afternl = FALSE;
+ }
+ if (*s1 == '\n')
+ afternl = TRUE;
+ putchar((*s1)); /* HACK: to keep proto happy */
+ }
+ putchar('\n');
+ afternl = TRUE;
+}
--- /dev/null
+/* $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 _DISPLAY_H
+#define _DISPLAY_H
+ void Dinit(void);
+ void Dterm(void);
+ void Dtrace(Tobj, int);
+#endif /* _DISPLAY_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* $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"
+#include "code.h"
+#include "tbl.h"
+#include "str.h"
+#include "exec.h"
+#include "internal.h"
+
+#define VOLATILE
+
+static lvar_t *lvarp;
+static int lvarn, llvari, flvari;
+#define LVARINCR 1000
+#define LVARSIZE sizeof (lvar_t)
+
+Tobj root, null;
+Tobj rtno;
+int Erun;
+int Eerrlevel, Estackdepth, Eshowbody, Eshowcalls, Eoktorun;
+
+#define PUSHJMP(op, np, b) op = (VOLATILE jmp_buf *) np, np = (jmp_buf *) &b
+#define POPJMP(op, np) np = (jmp_buf *) op
+
+/* longjmps for normal program execution */
+typedef enum {
+ PLJ_BREAK, PLJ_CONTINUE, PLJ_RETURN, PLJ_SIZE
+} PLJtype_t;
+static jmp_buf *pljbufp1, *pljbufp2;
+static PLJtype_t pljtype;
+
+/* longjmp for error handling */
+static jmp_buf *eljbufp;
+
+/* error levels and types */
+typedef enum {
+ ERR0, ERR1, ERR2, ERR3, ERR4, ERR5
+} errlevel_t;
+typedef enum {
+ ERRNOLHS, ERRNORHS, ERRNOSUCHFUNC, ERRBADARG, ERRARGMIS, ERRNOTATABLE,
+ ERRIFUNCERR, ERRRECRUN, ERRTABLECHANGED
+} errnum_t;
+static char *errnam[] = {
+ "no variable",
+ "no value",
+ "no such function",
+ "bad argument",
+ "argument number mismatch",
+ "not a table",
+ "internal function call error",
+ "recursive run attempt",
+ "table changed during a forin loop",
+};
+
+static int errdo;
+
+/* stack information */
+typedef struct sinfo_t {
+ Tobj co, fco;
+ int ci, fci;
+ int flvari, llvari;
+} sinfo_t;
+#define SINFOSIZE sizeof (sinfo_t)
+#define SINFOINCR 100
+static sinfo_t *sinfop;
+static int sinfoi, sinfon;
+
+typedef enum {
+ TNK_LI, TNK_O, TNK_S
+} tnktype_t;
+typedef struct tnk_t {
+ tnktype_t type;
+ union {
+ int li;
+ struct {
+ Tobj to, ko;
+ } tnko;
+ struct {
+ Ctype_t kt;
+ Tobj to, co;
+ int vi;
+ } tnks;
+ } u;
+} tnk_t;
+
+typedef struct Num_t {
+ Ctype_t type;
+ union {
+ long i;
+ double d;
+ Tobj no;
+ } u;
+} Num_t;
+
+static long rootm;
+static int running;
+
+static Tobj eeval(Tobj, int);
+static Tobj efcall(Tobj, int);
+static void ewhilest(Tobj, int);
+static void eforst(Tobj, int);
+static void eforinst(Tobj, int);
+
+static Tobj getval(Tobj, int);
+static int getvar(Tobj, int, tnk_t *);
+static void setvar(tnk_t, Tobj);
+static int boolop(Tobj);
+static int orderop(Tobj, Ctype_t, Tobj);
+static Tobj arithop(Num_t *, Ctype_t, Num_t *);
+static void err(int, int, Tobj, int);
+static void printbody(char *, int);
+
+void Einit(void)
+{
+ root = Ttable(100);
+ rootm = Mpushmark(root);
+ Tinss(root, "null", (null = Ttable(2)));
+ rtno = NULL;
+ pljbufp1 = pljbufp2 = NULL, pljtype = (PLJtype_t) 0;
+ eljbufp = NULL;
+ lvarp = Marrayalloc((long) LVARINCR * LVARSIZE);
+ lvarn = LVARINCR;
+ llvari = 0;
+ flvari = 0;
+ sinfop = Marrayalloc((long) SINFOINCR * SINFOSIZE);
+ sinfon = SINFOINCR;
+ sinfoi = 0;
+ Erun = FALSE;
+ running = 0;
+ Eoktorun = FALSE;
+}
+
+void Eterm(void)
+{
+ Marrayfree(sinfop), sinfop = NULL, sinfon = 0, sinfoi = 0;
+ Marrayfree(lvarp), lvarp = NULL, lvarn = 0, llvari = 0, flvari = 0;
+ rtno = NULL;
+ null = NULL;
+ Mpopmark(rootm);
+}
+
+Tobj Eunit(Tobj co)
+{
+ VOLATILE jmp_buf *oeljbufp;
+ VOLATILE int ownsinfoi;
+ VOLATILE long m;
+ VOLATILE Tobj lrtno;
+
+ jmp_buf eljbuf;
+
+#if 0
+ if (running && !Eoktorun) {
+ err(ERRRECRUN, ERR2, NULL, 0);
+ return NULL;
+ }
+#endif
+ Eoktorun = FALSE;
+
+ if (!co)
+ return NULL;
+
+ if (Tgettype(co) != T_CODE)
+ panic(POS, "Eunit", "argument type is not T_CODE");
+
+ m = Mpushmark(co);
+ PUSHJMP(oeljbufp, eljbufp, eljbuf);
+ ownsinfoi = sinfoi++;
+ if (sinfoi == sinfon) {
+ sinfop =
+ Marraygrow(sinfop, (long) (sinfon + SINFOINCR) * SINFOSIZE);
+ sinfon += SINFOINCR;
+ }
+ sinfop[ownsinfoi].co = co;
+ sinfop[ownsinfoi].ci = TCgetfp(co, 0);
+ sinfop[ownsinfoi].fco = NULL;
+ sinfop[ownsinfoi].flvari = flvari;
+ sinfop[ownsinfoi].llvari = llvari;
+ running++;
+ if (setjmp(*eljbufp))
+ lrtno = NULL;
+ else
+ lrtno = eeval(co, TCgetfp(co, 0));
+ running--;
+ rtno = NULL;
+ flvari = sinfop[ownsinfoi].flvari;
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ POPJMP(oeljbufp, eljbufp);
+ Mpopmark(m);
+ Erun = TRUE;
+ return lrtno;
+}
+
+/* shortcut: this function executes a piece of code that corresponds to
+ <internal func name> = function () internal "<internal func name>";
+*/
+Tobj Efunction(Tobj co, char *ifnam)
+{
+ Tobj v1o;
+ int fi;
+
+ fi = TCgetnext(co, TCgetfp(co, TCgetfp(co, 0)));
+ v1o = Tcode(TCgetaddr(co, fi), fi,
+ (int) TCgetinteger(co, TCgetfp(co, fi)));
+ Tinss(root, ifnam, v1o);
+ return v1o;
+}
+
+static Tobj eeval(Tobj co, int ci)
+{
+ Tobj v1o, v2o, v3o;
+ Ttype_t ttype;
+ Ctype_t ctype;
+ tnk_t tnk;
+ Num_t lnum, rnum;
+ long m1 = 0, m2;
+ int i1, i2, res;
+
+ tailrec:
+ errdo = TRUE;
+ v1o = NULL;
+ ctype = TCgettype(co, ci);
+ switch (ctype) {
+ case C_ASSIGN:
+ i1 = TCgetfp(co, ci);
+ if ((v1o = eeval(co, TCgetnext(co, i1))) == NULL) {
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ return NULL;
+ }
+ m1 = Mpushmark(v1o);
+ res = getvar(co, i1, &tnk);
+ Mpopmark(m1);
+ if (res == -1) {
+ err(ERRNOLHS, ERR3, co, i1);
+ return NULL;
+ }
+ setvar(tnk, v1o);
+ return v1o;
+ case C_OR:
+ case C_AND:
+ case C_NOT:
+ i1 = TCgetfp(co, ci);
+ if ((v1o = eeval(co, i1)) == NULL)
+ err(ERRNORHS, ERR4, co, i1);
+ switch (ctype) {
+ case C_OR:
+ if (boolop(v1o) == TRUE)
+ return Ttrue;
+ if ((v1o = eeval(co, TCgetnext(co, i1))) == NULL)
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ return (boolop(v1o) == TRUE) ? Ttrue : Tfalse;
+ case C_AND:
+ if (boolop(v1o) == FALSE)
+ return Tfalse;
+ if ((v1o = eeval(co, TCgetnext(co, i1))) == NULL)
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ return (boolop(v1o) == FALSE) ? Tfalse : Ttrue;
+ case C_NOT:
+ return (boolop(v1o) == TRUE) ? Tfalse : Ttrue;
+ default:
+ break;
+ }
+ /* NOT REACHED */
+ return Tfalse;
+ case C_EQ:
+ case C_NE:
+ case C_LT:
+ case C_LE:
+ case C_GT:
+ case C_GE:
+ i1 = TCgetfp(co, ci);
+ if ((v1o = eeval(co, i1)) == NULL)
+ err(ERRNORHS, ERR4, co, i1);
+ else
+ m1 = Mpushmark(v1o);
+ if ((v2o = eeval(co, TCgetnext(co, i1))) == NULL)
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ if (v1o)
+ Mpopmark(m1);
+ return (orderop(v1o, ctype, v2o) == TRUE) ? Ttrue : Tfalse;
+ case C_PLUS:
+ case C_MINUS:
+ case C_MUL:
+ case C_DIV:
+ case C_MOD:
+ case C_UMINUS:
+ i1 = TCgetfp(co, ci);
+ if ((lnum.type = TCgettype(co, i1)) == C_INTEGER)
+ lnum.u.i = TCgetinteger(co, i1);
+ else if (lnum.type == C_REAL)
+ lnum.u.d = TCgetreal(co, i1);
+ else if ((lnum.u.no = eeval(co, i1)) == NULL) {
+ err(ERRNORHS, ERR4, co, i1);
+ return NULL;
+ }
+ if (ctype == C_UMINUS) {
+ if (!(v1o = arithop(&lnum, ctype, NULL)))
+ err(ERRNORHS, ERR4, co, ci);
+ return v1o;
+ }
+ if (lnum.type != C_INTEGER && lnum.type != C_REAL)
+ m1 = Mpushmark(lnum.u.no);
+ i1 = TCgetnext(co, i1);
+ if ((rnum.type = TCgettype(co, i1)) == C_INTEGER)
+ rnum.u.i = TCgetinteger(co, i1);
+ else if (rnum.type == C_REAL)
+ rnum.u.d = TCgetreal(co, i1);
+ else if ((rnum.u.no = eeval(co, i1)) == NULL)
+ err(ERRNORHS, ERR4, co, i1);
+ if (lnum.type != C_INTEGER && lnum.type != C_REAL)
+ Mpopmark(m1);
+ if (!(v1o = arithop(&lnum, ctype, &rnum)))
+ err(ERRNORHS, ERR4, co, ci);
+ return v1o;
+ case C_PEXPR:
+ ci = TCgetfp(co, ci);
+ goto tailrec;
+ case C_FCALL:
+ return efcall(co, ci);
+ case C_INTEGER:
+ return Tinteger(TCgetinteger(co, ci));
+ case C_REAL:
+ return Treal(TCgetreal(co, ci));
+ case C_STRING:
+ return Tstring(TCgetstring(co, ci));
+ case C_GVAR:
+ case C_LVAR:
+ case C_PVAR:
+ return getval(co, ci);
+ case C_FUNCTION:
+ return Tcode(TCgetaddr(co, ci), ci,
+ (int) TCgetinteger(co, TCgetfp(co, ci)));
+ case C_TCONS:
+ v1o = Ttable(0);
+ m1 = Mpushmark(v1o);
+ for (i1 = TCgetfp(co, ci); i1 != C_NULL;
+ i1 = TCgetnext(co, TCgetnext(co, i1))) {
+ if (!(v3o = eeval(co, TCgetnext(co, i1)))) {
+ err(ERRNORHS, ERR4, co, TCgetnext(co, i1));
+ continue;
+ }
+ m2 = Mpushmark(v3o);
+ if (!(v2o = eeval(co, i1))) {
+ err(ERRNOLHS, ERR3, co, i1);
+ Mpopmark(m2);
+ continue;
+ }
+ ttype = Tgettype(v2o);
+ if (ttype == T_INTEGER || ttype == T_REAL || ttype == T_STRING)
+ Tinso(v1o, v2o, v3o);
+ else
+ err(ERRNOLHS, ERR1, co, i1);
+ }
+ Mpopmark(m1);
+ return v1o;
+ case C_STMT:
+ for (i1 = TCgetfp(co, ci); i1 != C_NULL;)
+ if ((i2 = TCgetnext(co, i1)) != C_NULL) {
+ eeval(co, i1);
+ i1 = i2;
+ } else {
+ ci = i1;
+ goto tailrec;
+ }
+ /* NOT REACHED */
+ break;
+ case C_IF:
+ i1 = TCgetfp(co, ci);
+ if (!(v1o = eeval(co, i1)))
+ err(ERRNORHS, ERR5, co, i1);
+ if (boolop(v1o) == TRUE) {
+ ci = TCgetnext(co, i1);
+ goto tailrec;
+ } else if ((ci = TCgetnext(co, TCgetnext(co, i1))) != C_NULL)
+ goto tailrec;
+ break;
+ case C_WHILE:
+ ewhilest(co, ci);
+ break;
+ case C_FOR:
+ eforst(co, ci);
+ break;
+ case C_FORIN:
+ eforinst(co, ci);
+ break;
+ case C_BREAK:
+ pljtype = PLJ_BREAK;
+ longjmp(*pljbufp1, 1);
+ /* NOT REACHED */
+ break;
+ case C_CONTINUE:
+ pljtype = PLJ_CONTINUE;
+ longjmp(*pljbufp1, 1);
+ /* NOT REACHED */
+ break;
+ case C_RETURN:
+ if ((i1 = TCgetfp(co, ci)) != C_NULL)
+ rtno = eeval(co, i1);
+ pljtype = PLJ_RETURN;
+ longjmp(*pljbufp2, 1);
+ /* NOT REACHED */
+ break;
+ default:
+ panic(POS, "eeval", "unknown program token type %d", ctype);
+ }
+ return v1o;
+}
+
+static Tobj efcall(Tobj co, int ci)
+{
+ VOLATILE jmp_buf *opljbufp1, *opljbufp2;
+ VOLATILE long m;
+ VOLATILE int bi, ownsinfoi, li, ln;
+
+ jmp_buf pljbuf;
+ Tobj fdo, vo, lrtno;
+ int i, fci, ai, di, di1, fid;
+
+ ownsinfoi = sinfoi++;
+ if (sinfoi == sinfon) {
+ sinfop =
+ Marraygrow(sinfop, (long) (sinfon + SINFOINCR) * SINFOSIZE);
+ sinfon += SINFOINCR;
+ }
+ sinfop[ownsinfoi].co = co;
+ sinfop[ownsinfoi].ci = ci;
+ sinfop[ownsinfoi].fco = NULL;
+ sinfop[ownsinfoi].flvari = flvari;
+ sinfop[ownsinfoi].llvari = llvari;
+ fci = TCgetfp(co, ci);
+ if (!(fdo = getval(co, fci)) || Tgettype(fdo) != T_CODE) {
+ err(ERRNOSUCHFUNC, ERR2, co, fci);
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+
+ m = Mpushmark((Tobj) fdo);
+ ai = TCgetfp(co, TCgetnext(co, fci));
+ ln = (int) TCgetinteger(fdo, (li = TCgetnext(fdo, TCgetfp(fdo, 0))));
+ di = TCgetnext(fdo, li);
+ bi = TCgetnext(fdo, di);
+ if (bi != C_NULL && TCgettype(fdo, bi) == C_INTERNAL) {
+ for (i = 0; ai != C_NULL; ai = TCgetnext(co, ai), i++) {
+ if (!(vo = eeval(co, ai))) {
+ err(ERRBADARG, ERR2, co, ai);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ if (llvari + 1 > lvarn) {
+ lvarp = Marraygrow(lvarp, (long) (llvari + 1) * LVARSIZE);
+ lvarn = llvari + 1;
+ }
+ lvarp[llvari].m = Mpushmark((lvarp[llvari].o = vo));
+ llvari++;
+ }
+ fid = (int) TCgetinteger(fdo, TCgetfp(fdo, bi));
+ if (Ifuncs[fid].min > i || Ifuncs[fid].max < i) {
+ err(ERRARGMIS, ERR2, co, ci);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ flvari = sinfop[ownsinfoi].llvari;
+ sinfop[ownsinfoi].fco = fdo;
+ sinfop[ownsinfoi].fci = bi;
+ if (fid < 0 || fid >= Ifuncn)
+ panic(POS, "efcall", "no such internal function: %d", fid);
+ rtno = Ttrue;
+ if ((*Ifuncs[fid].func) (i, &lvarp[flvari]) == L_FAILURE) {
+ rtno = NULL;
+ err(ERRIFUNCERR, ERR2, co, ci);
+ }
+ } else {
+ if (llvari + ln > lvarn) {
+ lvarp = Marraygrow(lvarp, (long) (llvari + ln) * LVARSIZE);
+ lvarn = llvari + ln;
+ }
+ di1 = TCgetfp(fdo, di);
+ for (i = 0; i < ln && di1 != C_NULL && ai != C_NULL;
+ i++, ai = TCgetnext(co, ai)) {
+ if (!(vo = eeval(co, ai))) {
+ err(ERRBADARG, ERR2, co, ai);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ lvarp[llvari].m = Mpushmark((lvarp[llvari].o = vo));
+ llvari++;
+ di1 = TCgetnext(fdo, di1);
+ }
+ if (di1 != C_NULL || ai != C_NULL) {
+ err(ERRARGMIS, ERR2, co, ci);
+ Mpopmark(m);
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ return NULL;
+ }
+ for (; i < ln; i++, llvari++)
+ lvarp[llvari].m = Mpushmark((lvarp[llvari].o = NULL));
+ flvari = sinfop[ownsinfoi].llvari;
+ PUSHJMP(opljbufp2, pljbufp2, pljbuf);
+ opljbufp1 = (VOLATILE jmp_buf *) pljbufp1;
+ if (setjmp(*pljbufp2)) {
+ ;
+ } else {
+ sinfop[ownsinfoi].fco = fdo;
+ for (; bi != C_NULL; bi = TCgetnext(fdo, bi)) {
+ sinfop[ownsinfoi].fci = bi;
+ if (TCgettype(fdo, bi) != C_DECL)
+ eeval((Tobj) fdo, bi);
+ }
+ }
+ POPJMP(opljbufp2, pljbufp2);
+ pljbufp1 = (jmp_buf *) opljbufp1;
+ }
+ flvari = sinfop[ownsinfoi].flvari;
+ llvari = sinfop[ownsinfoi].llvari;
+ sinfoi = ownsinfoi;
+ Mpopmark(m);
+ lrtno = rtno, rtno = NULL;
+ errdo = TRUE;
+ return lrtno;
+}
+
+static void ewhilest(Tobj co, int ci)
+{
+ VOLATILE jmp_buf *opljbufp;
+ VOLATILE jmp_buf pljbuf;
+ VOLATILE Tobj c1o;
+ VOLATILE int ei, si;
+
+ Tobj v1o;
+
+ c1o = (Tobj) co; /* protect argument from longjmp */
+ ei = TCgetfp(c1o, ci);
+ si = TCgetnext(c1o, ei);
+ PUSHJMP(opljbufp, pljbufp1, pljbuf);
+ for (;;) {
+ if (!(v1o = eeval((Tobj) c1o, ei)))
+ err(ERRNORHS, ERR5, c1o, ei);
+ if (boolop(v1o) == FALSE)
+ break;
+ if (setjmp(*pljbufp1)) {
+ if (pljtype == PLJ_CONTINUE)
+ continue;
+ else if (pljtype == PLJ_BREAK)
+ break;
+ }
+ eeval((Tobj) c1o, si);
+ }
+ POPJMP(opljbufp, pljbufp1);
+}
+
+static void eforst(Tobj co, int ci)
+{
+ VOLATILE jmp_buf *opljbufp;
+ VOLATILE jmp_buf pljbuf;
+ VOLATILE Tobj c1o;
+ VOLATILE int ei1, ei2, ei3, si, eisnop1, eisnop2, eisnop3;
+
+ Tobj v1o;
+
+ c1o = (Tobj) co; /* protect argument from longjmp */
+ ei1 = TCgetfp(c1o, ci);
+ ei2 = TCgetnext(c1o, ei1);
+ ei3 = TCgetnext(c1o, ei2);
+ si = TCgetnext(c1o, ei3);
+ eisnop1 = (TCgettype(c1o, ei1) == C_NOP);
+ eisnop2 = (TCgettype(c1o, ei2) == C_NOP);
+ eisnop3 = (TCgettype(c1o, ei3) == C_NOP);
+ PUSHJMP(opljbufp, pljbufp1, pljbuf);
+ if (!eisnop1)
+ eeval((Tobj) c1o, ei1);
+ for (;;) {
+ if (!eisnop2) {
+ if (!(v1o = eeval((Tobj) c1o, ei2)))
+ err(ERRNORHS, ERR5, c1o, ei2);
+ if (boolop(v1o) == FALSE)
+ break;
+ }
+ if (setjmp(*pljbufp1) != 0) {
+ if (pljtype == PLJ_CONTINUE);
+ else if (pljtype == PLJ_BREAK)
+ break;
+ } else {
+ eeval((Tobj) c1o, si);
+ }
+ if (!eisnop3)
+ eeval((Tobj) c1o, ei3);
+ }
+ POPJMP(opljbufp, pljbufp1);
+}
+
+static void eforinst(Tobj co, int ci)
+{
+ VOLATILE jmp_buf *opljbufp;
+ VOLATILE jmp_buf pljbuf;
+ VOLATILE Tobj tblo, c1o;
+ VOLATILE Tkvindex_t tkvi;
+ VOLATILE tnk_t tnk;
+ VOLATILE long km = 0, t, tm;
+ VOLATILE int ei1, ei2, si;
+
+ c1o = (Tobj) co; /* protect argument from longjmp */
+ ei1 = TCgetfp(c1o, ci);
+ ei2 = TCgetnext(c1o, ei1);
+ si = TCgetnext(c1o, ei2);
+ if (getvar((Tobj) c1o, ei1, (tnk_t *) & tnk) == -1) {
+ err(ERRNOLHS, ERR3, c1o, ei1);
+ return;
+ }
+ if (tnk.type == TNK_O)
+ km = Mpushmark(tnk.u.tnko.ko);
+ if (!(tblo = (Tobj) eeval((Tobj) c1o, ei2))) {
+ if (tnk.type == TNK_O)
+ Mpopmark(km);
+ err(ERRNORHS, ERR4, c1o, ei2);
+ return;
+ }
+ if (Tgettype(tblo) != T_TABLE) {
+ err(ERRNOTATABLE, ERR1, c1o, ei2);
+ return;
+ }
+ tm = Mpushmark(tblo);
+ PUSHJMP(opljbufp, pljbufp1, pljbuf);
+ t = Tgettime(tblo);
+ for (Tgetfirst((Tobj) tblo, (Tkvindex_t *) & tkvi); tkvi.kvp;
+ Tgetnext((Tkvindex_t *) & tkvi)) {
+ setvar(tnk, tkvi.kvp->ko);
+ if (setjmp(*pljbufp1) != 0) {
+ if (pljtype == PLJ_CONTINUE)
+ continue;
+ else if (pljtype == PLJ_BREAK)
+ break;
+ }
+ eeval((Tobj) c1o, si);
+ if (t != Tgettime(tblo)) {
+ err(ERRTABLECHANGED, ERR1, c1o, ei2);
+ break;
+ }
+ }
+ POPJMP(opljbufp, pljbufp1);
+ if (tnk.type == TNK_O)
+ Mpopmark(km);
+ Mpopmark(tm);
+}
+
+static Tobj getval(Tobj co, int ci)
+{
+ Tobj cvo = NULL, cko = NULL, cto = NULL;
+ Ctype_t ct = (Ctype_t) 0, vt = (Ctype_t) 0;
+ int vi, ni, nn = 0;
+
+ if ((ct = TCgettype(co, ci)) == C_LVAR) {
+ nn = (int) TCgetinteger(co, (ni = TCgetnext(co, TCgetfp(co, ci))));
+ cto = cvo = lvarp[flvari + nn].o;
+ if (!cto)
+ return NULL;
+ vi = TCgetnext(co, ni);
+ } else if (ct == C_GVAR) {
+ cto = root;
+ vi = TCgetfp(co, ci);
+ } else if (ct == C_PVAR)
+ return TCgetobject(co, ci);
+ else
+ return NULL;
+
+ while (vi != C_NULL) {
+ if (Tgettype(cto) != T_TABLE)
+ return NULL;
+ if ((vt = TCgettype(co, vi)) == C_STRING) {
+ if (!(cvo = Tfinds(cto, TCgetstring(co, vi))))
+ return NULL;
+ } else if (vt == C_INTEGER) {
+ if (!(cvo = Tfindi(cto, TCgetinteger(co, vi))))
+ return NULL;
+ } else if (vt == C_REAL) {
+ if (!(cvo = Tfindr(cto, TCgetreal(co, vi))))
+ return NULL;
+ } else {
+ if (!(cko = eeval(co, vi)) || !(cvo = Tfindo(cto, cko)))
+ return NULL;
+ }
+ cto = cvo;
+ vi = TCgetnext(co, vi);
+ }
+ return cvo;
+}
+
+static int getvar(Tobj co, int ci, tnk_t * tnkp)
+{
+ Tobj cvo = NULL, cko = NULL, cto = NULL;
+ Ctype_t ct = (Ctype_t) 0, vt = (Ctype_t) 0;
+ long m;
+ int vi, ovi, nn = 0, ni;
+
+ if ((ct = TCgettype(co, ci)) == C_LVAR) {
+ nn = (int) TCgetinteger(co, (ni = TCgetnext(co, TCgetfp(co, ci))));
+ cvo = cto = lvarp[flvari + nn].o;
+ vi = TCgetnext(co, ni);
+ if (vi != C_NULL && (!cvo || Tgettype(cvo) != T_TABLE))
+ Mresetmark(lvarp[flvari + nn].m,
+ (lvarp[flvari + nn].o = cvo = cto = Ttable(0)));
+ } else if (ct == C_GVAR) { /* else it's a global variable */
+ cvo = root;
+ vi = TCgetfp(co, ci);
+ } else {
+ return -1;
+ }
+
+ ovi = -1;
+ while (vi != C_NULL) {
+ cto = cvo;
+ if ((vt = TCgettype(co, vi)) == C_STRING) {
+ cvo = Tfinds(cto, TCgetstring(co, vi));
+ } else if (vt == C_INTEGER) {
+ cvo = Tfindi(cto, TCgetinteger(co, vi));
+ } else if (vt == C_REAL) {
+ cvo = Tfindr(cto, TCgetreal(co, vi));
+ } else {
+ if (!(cko = eeval(co, vi)) || !(T_ISSTRING(cko) ||
+ T_ISNUMBER(cko)))
+ return -1;
+ cvo = Tfindo(cto, cko);
+ }
+ ovi = vi, vi = TCgetnext(co, vi);
+ if (vi != C_NULL && (!cvo || Tgettype(cvo) != T_TABLE)) {
+ if (vt == C_STRING)
+ Tinss(cto, TCgetstring(co, ovi), (cvo = Ttable(0)));
+ else if (vt == C_INTEGER)
+ Tinsi(cto, TCgetinteger(co, ovi), (cvo = Ttable(0)));
+ else if (vt == C_REAL)
+ Tinsr(cto, TCgetreal(co, ovi), (cvo = Ttable(0)));
+ else
+ m = Mpushmark(cko), Tinso(cto, cko, (cvo = Ttable(0))),
+ Mpopmark(m);
+ }
+ }
+ if (ct == C_LVAR && ovi == -1) {
+ tnkp->type = TNK_LI;
+ tnkp->u.li = nn;
+ } else {
+ switch (vt) {
+ case C_STRING:
+ case C_INTEGER:
+ case C_REAL:
+ tnkp->type = TNK_S;
+ tnkp->u.tnks.kt = vt;
+ tnkp->u.tnks.to = cto;
+ tnkp->u.tnks.co = co;
+ tnkp->u.tnks.vi = ovi;
+ break;
+ default:
+ tnkp->type = TNK_O;
+ tnkp->u.tnko.to = cto;
+ tnkp->u.tnko.ko = cko;
+ break;
+ }
+ }
+ return 0;
+}
+
+static void setvar(tnk_t tnk, Tobj vo)
+{
+ switch (tnk.type) {
+ case TNK_LI:
+ Mresetmark(lvarp[flvari + tnk.u.li].m,
+ (lvarp[flvari + tnk.u.li].o = vo));
+ break;
+ case TNK_O:
+ Tinso(tnk.u.tnko.to, tnk.u.tnko.ko, vo);
+ break;
+ default:
+ switch (tnk.u.tnks.kt) {
+ case C_STRING:
+ Tinss(tnk.u.tnks.to,
+ TCgetstring(tnk.u.tnks.co, tnk.u.tnks.vi), vo);
+ break;
+ case C_INTEGER:
+ Tinsi(tnk.u.tnks.to,
+ TCgetinteger(tnk.u.tnks.co, tnk.u.tnks.vi), vo);
+ break;
+ case C_REAL:
+ Tinsr(tnk.u.tnks.to, TCgetreal(tnk.u.tnks.co, tnk.u.tnks.vi),
+ vo);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+}
+
+static int boolop(Tobj vo)
+{
+ long i;
+ double d;
+
+ if (!vo)
+ return FALSE;
+
+ switch (Tgettype(vo)) {
+ case T_INTEGER:
+ i = Tgetinteger(vo);
+ return (i == 0) ? FALSE : TRUE;
+ case T_REAL:
+ d = Tgetreal(vo);
+ return (d == 0.0) ? FALSE : TRUE;
+ case T_TABLE:
+ if (vo == null)
+ return FALSE;
+ return TRUE;
+ default:
+ return TRUE;
+ }
+}
+
+static int orderop(Tobj v1o, Ctype_t op, Tobj v2o)
+{
+ Ctype_t t1, t2;
+ long i1, i2;
+ int r;
+ double d1, d2;
+
+ if (!v1o || !v2o) {
+ if ((v1o || v2o) && op == C_NE)
+ return TRUE;
+ return FALSE;
+ }
+ t1 = (Ctype_t) Tgettype(v1o), t2 = (Ctype_t) Tgettype(v2o);
+ if (t1 == T_STRING && t2 == T_STRING) {
+ r = Strcmp(Tgetstring(v1o), Tgetstring(v2o));
+ } else if (t1 == T_INTEGER && t2 == T_INTEGER) {
+ i1 = Tgetinteger(v1o), i2 = Tgetinteger(v2o);
+ r = (i1 == i2) ? 0 : ((i1 < i2) ? -1 : 1);
+ } else if (t1 == T_INTEGER && t2 == T_REAL) {
+ i1 = Tgetinteger(v1o), d2 = Tgetreal(v2o);
+ r = (i1 == d2) ? 0 : ((i1 < d2) ? -1 : 1);
+ } else if (t1 == T_REAL && t2 == T_INTEGER) {
+ d1 = Tgetreal(v1o), i2 = Tgetinteger(v2o);
+ r = (d1 == i2) ? 0 : ((d1 < i2) ? -1 : 1);
+ } else if (t1 == T_REAL && t2 == T_REAL) {
+ d1 = Tgetreal(v1o), d2 = Tgetreal(v2o);
+ r = (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+ } else if (t1 == t2) {
+ if (op != C_EQ && op != C_NE)
+ return FALSE;
+ r = (v1o == v2o) ? 0 : 1;
+ } else {
+ return FALSE;
+ }
+ switch (op) {
+ case C_EQ:
+ return (r == 0) ? TRUE : FALSE;
+ case C_NE:
+ return (r != 0) ? TRUE : FALSE;
+ case C_LT:
+ return (r < 0) ? TRUE : FALSE;
+ case C_LE:
+ return (r <= 0) ? TRUE : FALSE;
+ case C_GT:
+ return (r > 0) ? TRUE : FALSE;
+ case C_GE:
+ return (r >= 0) ? TRUE : FALSE;
+ default:
+ break;
+ }
+ panic(POS, "orderop", "bad op code");
+ return FALSE; /* NOT REACHED */
+}
+
+static Tobj arithop(Num_t * lnum, Ctype_t op, Num_t * rnum)
+{
+ double d1, d2, d3 = 0.0;
+
+ if (!rnum && op != C_UMINUS)
+ return NULL;
+ if (lnum->type == C_INTEGER)
+ d1 = lnum->u.i;
+ else if (lnum->type == C_REAL)
+ d1 = lnum->u.d;
+ else if (!lnum->u.no)
+ return NULL;
+ else if (Tgettype(lnum->u.no) == T_INTEGER)
+ d1 = Tgetinteger(lnum->u.no);
+ else if (Tgettype(lnum->u.no) == T_REAL)
+ d1 = Tgetreal(lnum->u.no);
+ else
+ return NULL;
+ if (op == C_UMINUS) {
+ d3 = -d1;
+ goto result;
+ }
+ if (rnum->type == C_INTEGER)
+ d2 = rnum->u.i;
+ else if (rnum->type == C_REAL)
+ d2 = rnum->u.d;
+ else if (!rnum->u.no)
+ return NULL;
+ else if (Tgettype(rnum->u.no) == T_INTEGER)
+ d2 = Tgetinteger(rnum->u.no);
+ else if (Tgettype(rnum->u.no) == T_REAL)
+ d2 = Tgetreal(rnum->u.no);
+ else
+ return NULL;
+ switch (op) {
+ case C_PLUS:
+ d3 = d1 + d2;
+ break;
+ case C_MINUS:
+ d3 = d1 - d2;
+ break;
+ case C_MUL:
+ d3 = d1 * d2;
+ break;
+ case C_DIV:
+ d3 = d1 / d2;
+ break;
+ case C_MOD:
+ d3 = (long) d1 % (long) d2;
+ break;
+ default:
+ break;
+ }
+ result:
+ if (d3 == (double) (long) d3)
+ return Tinteger((long) d3);
+ return Treal(d3);
+}
+
+static void err(int errnum, int level, Tobj co, int ci)
+{
+ char *s;
+ int si, i;
+
+ if (level > Eerrlevel || !errdo)
+ return;
+ s = "";
+ fprintf(stderr, "runtime error: %s\n", errnam[errnum]);
+ if (!co)
+ return;
+ if (Estackdepth < 1)
+ return;
+ if (!sinfop[(si = sinfoi - 1)].fco && si > 0)
+ si--;
+ if (Eshowbody > 0) {
+ if (co == sinfop[si].fco)
+ s = Scfull(co, 0, ci);
+ else if (co == sinfop[si].co)
+ s = Scfull(co, TCgetfp(co, 0), ci);
+ printbody(s, Eshowbody), free(s);
+ if (Estackdepth == 1) {
+ fprintf(stderr, "\n");
+ errdo = FALSE;
+ }
+ for (i = si; i >= 0; i--) {
+ if (sinfop[i].fco) {
+ s = Scfull(sinfop[i].fco, 0, sinfop[i].fci);
+ printbody(s, Eshowbody), free(s);
+ }
+ }
+ s = Scfull(sinfop[0].co, TCgetfp(sinfop[0].co, 0), sinfop[0].ci);
+ printbody(s, Eshowbody), free(s);
+ }
+ fprintf(stderr, "\n");
+ errdo = FALSE;
+}
+
+static void printbody(char *s, int mode)
+{
+ char *s1, *s2;
+ char c;
+
+ if (mode == 2) {
+ fprintf(stderr, "%s\n", s);
+ return;
+ }
+ c = '\000';
+ for (s1 = s; *s1; s1++)
+ if (*s1 == '>' && *(s1 + 1) && *(s1 + 1) == '>')
+ break;
+ if (!*s1)
+ return;
+ for (; s1 != s; s1--)
+ if (*(s1 - 1) == '\n')
+ break;
+ for (s2 = s1; *s2; s2++)
+ if (*s2 == '\n')
+ break;
+ if (*s2)
+ c = *s2, *s2 = '\000';
+ fprintf(stderr, "%s\n", s1);
+ if (c)
+ *s2 = c;
+}
--- /dev/null
+/* $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 _EXEC_H
+#define _EXEC_H
+ typedef struct Tonm_t lvar_t;
+
+ extern Tobj root, null;
+ extern Tobj rtno;
+ extern int Erun;
+ extern int Eerrlevel, Estackdepth, Eshowbody, Eshowcalls, Eoktorun;
+
+ void Einit(void);
+ void Eterm(void);
+ Tobj Eunit(Tobj);
+ Tobj Efunction(Tobj, char *);
+#endif /* _EXEC_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* $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 "g.h"
+#include "gcommon.h"
+#include "mem.h"
+
+Gwidget_t *Gwidgets;
+int Gwidgetn;
+
+Gbitmap_t *Gbitmaps;
+int Gbitmapn;
+#define BITMAPINCR 10
+#define BITMAPSIZE sizeof (Gbitmap_t)
+
+char *Gdefaultfont;
+int Gneedredraw;
+int Gbuttonsdown;
+int Gerrflag;
+int Gerrno;
+
+char *texts;
+int textn;
+
+static long wsizes[G_WTYPESIZE];
+static Gtextline_t tlarray[1000];
+
+Gwattrmap_t Gwattrmap[] = {
+ {G_ATTRORIGIN, G_ATTRTYPEPOINT, "origin",},
+ {G_ATTRSIZE, G_ATTRTYPESIZE, "size",},
+ {G_ATTRBORDERWIDTH, G_ATTRTYPEINT, "borderwidth",},
+ {G_ATTRNAME, G_ATTRTYPETEXT, "name",},
+ {G_ATTRTEXT, G_ATTRTYPETEXT, "text",},
+ {G_ATTRAPPENDTEXT, G_ATTRTYPETEXT, "appendtext",},
+ {G_ATTRSELECTION, G_ATTRTYPETEXT, "selection",},
+ {G_ATTRCURSOR, G_ATTRTYPETEXT, "cursor",},
+ {G_ATTRMODE, G_ATTRTYPETEXT, "mode",},
+ {G_ATTRLAYOUT, G_ATTRTYPETEXT, "layout",},
+ {G_ATTRZORDER, G_ATTRTYPETEXT, "zorder",},
+ {G_ATTRCOLOR, G_ATTRTYPECOLOR, "color",},
+ {G_ATTRVIEWPORT, G_ATTRTYPESIZE, "viewport",},
+ {G_ATTRWINDOW, G_ATTRTYPERECT, "window",},
+ {G_ATTRWINDOWID, G_ATTRTYPETEXT, "windowid",},
+ {G_ATTRCHILDCENTER, G_ATTRTYPEPOINT, "childcenter",},
+ {G_ATTRNEWLINECB, G_ATTRTYPEFUNC, "newlinecb",},
+ {G_ATTRRESIZECB, G_ATTRTYPEFUNC, "resizecb",},
+ {G_ATTRBUTTONCB, G_ATTRTYPEFUNC, "buttoncb",},
+ {G_ATTREVENTCB, G_ATTRTYPEFUNC, "eventcb",},
+ {G_ATTRUSERDATA, G_ATTRTYPEFUNC, "userdata",},
+ {-1, (Gwattrtype_t) - 1, NULL,},
+};
+
+static int arrayattr[] = {
+ G_ATTRSIZE,
+ G_ATTRBORDERWIDTH,
+ G_ATTRMODE,
+ G_ATTRLAYOUT,
+ G_ATTRCOLOR,
+ G_ATTRWINDOWID,
+ G_ATTRRESIZECB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int buttonattr[] = {
+ G_ATTRSIZE,
+ G_ATTRBORDERWIDTH,
+ G_ATTRTEXT,
+ G_ATTRCOLOR,
+ G_ATTRWINDOWID,
+ G_ATTRBUTTONCB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int canvasattr[] = {
+ G_ATTRSIZE,
+ G_ATTRBORDERWIDTH,
+#ifdef FEATURE_GMAP
+ G_ATTRMODE,
+#endif
+ G_ATTRCURSOR,
+ G_ATTRCOLOR,
+ G_ATTRVIEWPORT,
+ G_ATTRWINDOW,
+ G_ATTRWINDOWID,
+ G_ATTREVENTCB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int labelattr[] = {
+ G_ATTRSIZE,
+ G_ATTRBORDERWIDTH,
+ G_ATTRTEXT,
+ G_ATTRCOLOR,
+ G_ATTRWINDOWID,
+ G_ATTREVENTCB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int menuattr[] = {
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int pcanvasattr[] = {
+ G_ATTRORIGIN,
+ G_ATTRSIZE,
+ G_ATTRNAME,
+ G_ATTRMODE,
+ G_ATTRCOLOR,
+ G_ATTRWINDOW,
+ G_ATTRWINDOWID,
+ G_ATTREVENTCB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int queryattr[] = {
+ G_ATTRMODE,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int scrollattr[] = {
+ G_ATTRSIZE,
+ G_ATTRBORDERWIDTH,
+ G_ATTRCHILDCENTER,
+ G_ATTRMODE,
+ G_ATTRCOLOR,
+ G_ATTRWINDOWID,
+ G_ATTRUSERDATA,
+ -1,
+};
+
+static int textattr[] = {
+ G_ATTRSIZE,
+ G_ATTRBORDERWIDTH,
+ G_ATTRTEXT,
+ G_ATTRAPPENDTEXT,
+ G_ATTRSELECTION,
+ G_ATTRMODE,
+ G_ATTRCOLOR,
+ G_ATTRWINDOWID,
+ G_ATTRNEWLINECB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+static int viewattr[] = {
+ G_ATTRORIGIN,
+ G_ATTRSIZE,
+ G_ATTRNAME,
+ G_ATTRCOLOR,
+ G_ATTRZORDER,
+ G_ATTRWINDOWID,
+ G_ATTREVENTCB,
+ G_ATTRUSERDATA,
+ -1
+};
+
+Gwlist_t Gwlist[] = {
+ {G_ARRAYWIDGET, "array", &arrayattr[0],},
+ {G_BUTTONWIDGET, "button", &buttonattr[0],},
+ {G_CANVASWIDGET, "canvas", &canvasattr[0],},
+ {G_LABELWIDGET, "label", &labelattr[0],},
+ {G_MENUWIDGET, "menu", &menuattr[0],},
+ {G_PCANVASWIDGET, "ps", &pcanvasattr[0],},
+ {G_QUERYWIDGET, "query", &queryattr[0],},
+ {G_SCROLLWIDGET, "scroll", &scrollattr[0],},
+ {G_TEXTWIDGET, "text", &textattr[0],},
+ {G_VIEWWIDGET, "view", &viewattr[0],},
+ {-1, NULL, NULL,},
+};
+
+static char *errmsg[] = {
+ /* Gerrno starts at 1 */ "no error",
+ /* G_ERRBADATTRID */ "bad attribute id %d",
+ /* G_ERRBADATTRVALUE */ "bad attribute value %s",
+ /* G_ERRBADCOLORINDEX */ "bad color index %d",
+ /* G_ERRBADPARENTWIDGETID */ "bad parent widget id %d",
+ /* G_ERRBADWIDGETID */ "bad widget id %d",
+ /* G_ERRBADWIDGETTYPE */ "bad widget type %d",
+ /* G_ERRCANNOTCREATEWIDGET */ "cannot create widget",
+ /* G_ERRCANNOTGETATTR */ "cannot get attribute %s",
+ /* G_ERRCANNOTOPENFILE */ "cannot open file %s",
+ /* G_ERRCANNOTSETATTR1 */
+ "cannot set attribute %s in createwidget",
+ /* G_ERRCANNOTSETATTR2 */
+ "cannot set attribute %s in setwidgetattr",
+ /* G_ERRINITFAILED */ "initialization failed",
+ /* G_ERRNOCHILDWIDGET */ "no child widget",
+ /* G_ERRNOPARENTWIDGET */ "no parent widget",
+ /* G_ERRNOSUCHCURSOR */ "no such cursor %s",
+ /* G_ERRNOTACANVAS */ "widget %d is not a canvas",
+ /* G_ERRNOTIMPLEMENTED */ "not implemented",
+ /* G_ERRNOTSUPPORTED */ "not supported"
+ /* G_ERRBADBITMAPID */ "bad bitmap id %d",
+ /* G_ERRCANNOTCREATEBITMAP */ "cannot create bitmap",
+ /* G_ERRNOBITMAP */ "no bitmap",
+ /* G_ERRCANNOTREADBITMAP */ "cannot read bitmap",
+};
+
+static int unpackstring(char *);
+
+int Ginit(void)
+{
+ int wi, bi;
+
+ wsizes[G_ARRAYWIDGET] = AWSIZE;
+ wsizes[G_BUTTONWIDGET] = BWSIZE;
+ wsizes[G_CANVASWIDGET] = CWSIZE;
+ wsizes[G_LABELWIDGET] = LWSIZE;
+ wsizes[G_MENUWIDGET] = MWSIZE;
+ wsizes[G_PCANVASWIDGET] = PWSIZE;
+ wsizes[G_QUERYWIDGET] = QWSIZE;
+ wsizes[G_SCROLLWIDGET] = SWSIZE;
+ wsizes[G_TEXTWIDGET] = TWSIZE;
+ wsizes[G_VIEWWIDGET] = VWSIZE;
+ Gwidgets = Marrayalloc((long) WIDGETINCR * WIDGETSIZE);
+ Gwidgetn = WIDGETINCR;
+ for (wi = 0; wi < Gwidgetn; wi++)
+ Gwidgets[wi].inuse = FALSE;
+ Gbitmapn = BITMAPINCR;
+ Gbitmaps = Marrayalloc((long) Gbitmapn * BITMAPSIZE);
+ for (bi = 0; bi < Gbitmapn; bi++)
+ Gbitmaps[bi].inuse = FALSE;
+ Gneedredraw = FALSE;
+ Gbuttonsdown = 0;
+ Gdefaultfont = "";
+ Gerrflag = FALSE;
+ textn = 100;
+ texts = Marrayalloc((long) textn);
+ texts[0] = '\0';
+ Ginitgraphics();
+ return 0;
+}
+
+int Gterm(void)
+{
+ int wi;
+
+ for (wi = 0; wi < Gwidgetn; wi++)
+ if (Gwidgets[wi].inuse)
+ Gdestroywidget(wi);
+ Gtermgraphics();
+ Marrayfree(texts), texts = NULL, textn = 0;
+ Marrayfree(Gwidgets), Gwidgets = NULL, Gwidgetn = 0;
+ Marrayfree(Gbitmaps), Gbitmaps = NULL, Gbitmapn = 0;
+ return 0;
+}
+
+int Gcreatewidget(int pwi, int type, int attrn, Gwattr_t * attrp)
+{
+ Gwidget_t *parent, *widget;
+ int rtn;
+
+ if ((pwi != -1) && (pwi < 0 || pwi > Gwidgetn || !Gwidgets[pwi].inuse)) {
+ Gerr(POS, G_ERRBADPARENTWIDGETID, pwi);
+ return -1;
+ }
+ if (type < 0 || type >= G_WTYPESIZE) {
+ Gerr(POS, G_ERRBADWIDGETTYPE, type);
+ return -1;
+ }
+ widget = newwidget(type);
+ widget->inuse = TRUE;
+ widget->pwi = pwi;
+ parent = (pwi == -1) ? NULL : &Gwidgets[pwi];
+ rtn = -1;
+ switch (type) {
+ case G_ARRAYWIDGET:
+ rtn = GAcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_BUTTONWIDGET:
+ rtn = GBcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_CANVASWIDGET:
+ rtn = GCcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_LABELWIDGET:
+ rtn = GLcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_MENUWIDGET:
+ rtn = GMcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_PCANVASWIDGET:
+ rtn = GPcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_QUERYWIDGET:
+ rtn = GQcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_SCROLLWIDGET:
+ rtn = GScreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_TEXTWIDGET:
+ rtn = GTcreatewidget(parent, widget, attrn, attrp);
+ break;
+ case G_VIEWWIDGET:
+ rtn = GVcreatewidget(parent, widget, attrn, attrp);
+ break;
+ }
+ if (rtn == -1) {
+ widget->inuse = FALSE;
+ return -1;
+ }
+ return widget - &Gwidgets[0];
+}
+
+int Gsetwidgetattr(int wi, int attrn, Gwattr_t * attrp)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_ARRAYWIDGET:
+ return GAsetwidgetattr(widget, attrn, attrp);
+ case G_BUTTONWIDGET:
+ return GBsetwidgetattr(widget, attrn, attrp);
+ case G_CANVASWIDGET:
+ return GCsetwidgetattr(widget, attrn, attrp);
+ case G_LABELWIDGET:
+ return GLsetwidgetattr(widget, attrn, attrp);
+ case G_MENUWIDGET:
+ return GMsetwidgetattr(widget, attrn, attrp);
+ case G_PCANVASWIDGET:
+ return GPsetwidgetattr(widget, attrn, attrp);
+ case G_QUERYWIDGET:
+ return GQsetwidgetattr(widget, attrn, attrp);
+ case G_SCROLLWIDGET:
+ return GSsetwidgetattr(widget, attrn, attrp);
+ case G_TEXTWIDGET:
+ return GTsetwidgetattr(widget, attrn, attrp);
+ case G_VIEWWIDGET:
+ return GVsetwidgetattr(widget, attrn, attrp);
+ }
+ return -1;
+}
+
+int Ggetwidgetattr(int wi, int attrn, Gwattr_t * attrp)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_ARRAYWIDGET:
+ return GAgetwidgetattr(widget, attrn, attrp);
+ case G_BUTTONWIDGET:
+ return GBgetwidgetattr(widget, attrn, attrp);
+ case G_CANVASWIDGET:
+ return GCgetwidgetattr(widget, attrn, attrp);
+ case G_LABELWIDGET:
+ return GLgetwidgetattr(widget, attrn, attrp);
+ case G_MENUWIDGET:
+ return GMgetwidgetattr(widget, attrn, attrp);
+ case G_PCANVASWIDGET:
+ return GPgetwidgetattr(widget, attrn, attrp);
+ case G_QUERYWIDGET:
+ return GQgetwidgetattr(widget, attrn, attrp);
+ case G_SCROLLWIDGET:
+ return GSgetwidgetattr(widget, attrn, attrp);
+ case G_TEXTWIDGET:
+ return GTgetwidgetattr(widget, attrn, attrp);
+ case G_VIEWWIDGET:
+ return GVgetwidgetattr(widget, attrn, attrp);
+ }
+ return -1;
+}
+
+int Gdestroywidget(int wi)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_ARRAYWIDGET:
+ GAdestroywidget(widget);
+ break;
+ case G_BUTTONWIDGET:
+ GBdestroywidget(widget);
+ break;
+ case G_CANVASWIDGET:
+ GCdestroywidget(widget);
+ break;
+ case G_LABELWIDGET:
+ GLdestroywidget(widget);
+ break;
+ case G_MENUWIDGET:
+ GMdestroywidget(widget);
+ break;
+ case G_PCANVASWIDGET:
+ GPdestroywidget(widget);
+ break;
+ case G_QUERYWIDGET:
+ GQdestroywidget(widget);
+ break;
+ case G_SCROLLWIDGET:
+ GSdestroywidget(widget);
+ break;
+ case G_TEXTWIDGET:
+ GTdestroywidget(widget);
+ break;
+ case G_VIEWWIDGET:
+ GVdestroywidget(widget);
+ break;
+ }
+ /* HACK: should do switch on type ... */
+ free(widget->u.c);
+ widget->inuse = FALSE;
+ return 0;
+}
+
+int Gqueryask(int wi, char *prompt, char *args,
+ char *responsep, int responsen)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ return GQqueryask(widget, prompt, args, responsep, responsen);
+}
+
+int Gmenuaddentries(int wi, int en, char **ep)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ return GMmenuaddentries(widget, en, ep);
+}
+
+int Gmenudisplay(int pwi, int wi)
+{
+ Gwidget_t *parent, *widget;
+
+ if (pwi < 0 || pwi > Gwidgetn || !Gwidgets[pwi].inuse) {
+ Gerr(POS, G_ERRBADPARENTWIDGETID, wi);
+ return -1;
+ }
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ parent = &Gwidgets[pwi];
+ widget = &Gwidgets[wi];
+ return GMmenudisplay(parent, widget);
+}
+
+/* functions for drawing on canvas and pcanvas widgets */
+
+int Gcanvasclear(int wi)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCcanvasclear(widget);
+ case G_PCANVASWIDGET:
+ return GPcanvasclear(widget);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Gsetgfxattr(int wi, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCsetgfxattr(widget, ap);
+ case G_PCANVASWIDGET:
+ return GPsetgfxattr(widget, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Ggetgfxattr(int wi, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCgetgfxattr(widget, ap);
+ case G_PCANVASWIDGET:
+ return GPgetgfxattr(widget, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Garrow(int wi, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCarrow(widget, gp1, gp2, ap);
+ case G_PCANVASWIDGET:
+ return GParrow(widget, gp1, gp2, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Gline(int wi, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCline(widget, gp1, gp2, ap);
+ case G_PCANVASWIDGET:
+ return GPline(widget, gp1, gp2, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Gbox(int wi, Grect_t gr, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCbox(widget, gr, ap);
+ case G_PCANVASWIDGET:
+ return GPbox(widget, gr, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Gpolygon(int wi, int gpn, Gpoint_t * gpp, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCpolygon(widget, gpn, gpp, ap);
+ case G_PCANVASWIDGET:
+ return GPpolygon(widget, gpn, gpp, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Gsplinegon(int wi, int gpn, Gpoint_t * gpp, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCsplinegon(widget, gpn, gpp, ap);
+ case G_PCANVASWIDGET:
+ return GPsplinegon(widget, gpn, gpp, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Garc(int wi, Gpoint_t gc, Gsize_t gs, double ang1, double ang2,
+ Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCarc(widget, gc, gs, ang1, ang2, ap);
+ case G_PCANVASWIDGET:
+ return GParc(widget, gc, gs, ang1, ang2, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Gtext(int wi, char *string, Gpoint_t go, char *fn, double fs,
+ char *justs, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+ char js[2];
+ int n;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ if (string[0] == '\000')
+ return 0;
+ n = unpackstring(string);
+ if (!justs[0] || !justs[1])
+ js[0] = 'c', js[1] = 'c';
+ else {
+ js[0] = justs[0], js[1] = justs[1];
+ if (js[0] != 'l' && js[0] != 'c' && js[0] != 'r')
+ js[0] = 'c';
+ if (js[1] != 'd' && js[1] != 'c' && js[1] != 'u')
+ js[1] = 'c';
+ }
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCtext(widget, &tlarray[0], n, go, fn, fs, &js[0], ap);
+ case G_PCANVASWIDGET:
+ return GPtext(widget, &tlarray[0], n, go, fn, fs, &js[0], ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Ggettextsize(int wi, char *string, char *fn, double fs, Gsize_t * gsp)
+{
+ Gwidget_t *widget;
+ int n;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ if (widget->type != G_CANVASWIDGET) {
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+ }
+ if (string[0] == '\000') {
+ gsp->x = gsp->y = 0.0;
+ return 0;
+ }
+ n = unpackstring(string);
+ return GCgettextsize(widget, &tlarray[0], n, fn, fs, gsp);
+}
+
+int Gcreatebitmap(int wi, Gsize_t s)
+{
+ Gwidget_t *widget;
+ Gbitmap_t *bitmap;
+ int rtn;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADPARENTWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+ }
+ bitmap = newbitmap();
+ bitmap->inuse = TRUE;
+ bitmap->canvas = wi;
+ rtn = -1;
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ rtn = GCcreatebitmap(widget, bitmap, s);
+ break;
+ case G_PCANVASWIDGET:
+ rtn = GPcreatebitmap(widget, bitmap, s);
+ break;
+ }
+ if (rtn == -1) {
+ bitmap->inuse = FALSE;
+ return -1;
+ }
+ return bitmap - &Gbitmaps[0];
+}
+
+int Gdestroybitmap(int bi)
+{
+ Gbitmap_t *bitmap;
+
+ if (bi < 0 || bi > Gbitmapn || !Gbitmaps[bi].inuse) {
+ Gerr(POS, G_ERRBADBITMAPID, bi);
+ return -1;
+ }
+ bitmap = &Gbitmaps[bi];
+ switch (bitmap->ctype) {
+ case G_CANVASWIDGET:
+ GCdestroybitmap(bitmap);
+ break;
+ case G_PCANVASWIDGET:
+ GPdestroybitmap(bitmap);
+ break;
+ }
+ bitmap->inuse = FALSE;
+ return 0;
+}
+
+int Greadbitmap(int wi, FILE * fp)
+{
+ Gwidget_t *widget;
+ Gbitmap_t *bitmap;
+ int rtn;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADPARENTWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+ }
+ bitmap = newbitmap();
+ bitmap->inuse = TRUE;
+ bitmap->canvas = wi;
+ rtn = -1;
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ rtn = GCreadbitmap(widget, bitmap, fp);
+ break;
+ case G_PCANVASWIDGET:
+ rtn = GPreadbitmap(widget, bitmap, fp);
+ break;
+ }
+ if (rtn == -1) {
+ bitmap->inuse = FALSE;
+ return -1;
+ }
+ return bitmap - &Gbitmaps[0];
+}
+
+int Gwritebitmap(FILE * fp, int bi)
+{
+ Gbitmap_t *bitmap;
+ int rtn;
+
+ if (bi < 0 || bi > Gbitmapn || !Gbitmaps[bi].inuse) {
+ Gerr(POS, G_ERRBADBITMAPID, bi);
+ return -1;
+ }
+ bitmap = &Gbitmaps[bi];
+ rtn = -1;
+ switch (bitmap->ctype) {
+ case G_CANVASWIDGET:
+ rtn = GCwritebitmap(bitmap, fp);
+ break;
+ case G_PCANVASWIDGET:
+ rtn = GPwritebitmap(bitmap, fp);
+ break;
+ }
+ if (rtn == -1)
+ return -1;
+ return 0;
+}
+
+int Gbitblt(int wi, Gpoint_t gp, Grect_t gr, int bi,
+ char *mode, Ggattr_t * ap)
+{
+ Gwidget_t *widget;
+ Gbitmap_t *bitmap;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ if (bi < 0 || bi > Gbitmapn || !Gbitmaps[bi].inuse) {
+ Gerr(POS, G_ERRBADBITMAPID, bi);
+ return -1;
+ }
+ bitmap = &Gbitmaps[bi];
+ switch (widget->type) {
+ case G_CANVASWIDGET:
+ return GCbitblt(widget, gp, gr, bitmap, mode, ap);
+ case G_PCANVASWIDGET:
+ return GPbitblt(widget, gp, gr, bitmap, mode, ap);
+ }
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+}
+
+int Ggetmousecoords(int wi, Gpoint_t * gsp, int *count)
+{
+ Gwidget_t *widget;
+
+ if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
+ Gerr(POS, G_ERRBADWIDGETID, wi);
+ return -1;
+ }
+ widget = &Gwidgets[wi];
+ if (widget->type != G_CANVASWIDGET) {
+ Gerr(POS, G_ERRNOTACANVAS, wi);
+ return -1;
+ }
+ return GCgetmousecoords(widget, gsp, count);
+}
+
+Gwidget_t *newwidget(int type)
+{
+ Gwidget_t *new;
+ int wi;
+
+ for (wi = 0; wi < Gwidgetn; wi++)
+ if (!Gwidgets[wi].inuse)
+ goto found;
+
+ Gwidgets = Marraygrow(Gwidgets,
+ (long) (Gwidgetn + WIDGETINCR) * WIDGETSIZE);
+ for (wi = Gwidgetn; wi < Gwidgetn + WIDGETINCR; wi++)
+ Gwidgets[wi].inuse = FALSE;
+ wi = Gwidgetn, Gwidgetn += WIDGETINCR;
+
+ found:
+ new = &Gwidgets[wi];
+ new->type = type;
+ new->w = 0;
+ new->udata = 0;
+ /* HACK: should do a switch on type, but ... */
+ if (!(new->u.c = (Gcw_t *) malloc(wsizes[type])))
+ panic(POS, "newwidget", "cannot allocate data");
+ return new;
+}
+
+Gwidget_t *findwidget(unsigned long w, int type)
+{
+ int wi;
+
+ if (type == G_WTYPESIZE) {
+ for (wi = 0; wi < Gwidgetn; wi++)
+ if (Gwidgets[wi].inuse && (unsigned long) Gwidgets[wi].w == w)
+ return &Gwidgets[wi];
+ } else {
+ for (wi = 0; wi < Gwidgetn; wi++)
+ if (Gwidgets[wi].inuse && Gwidgets[wi].type == type &&
+ (unsigned long) Gwidgets[wi].w == w)
+ return &Gwidgets[wi];
+ }
+ return NULL;
+}
+
+Gbitmap_t *newbitmap(void)
+{
+ Gbitmap_t *new;
+ int bi;
+
+ for (bi = 0; bi < Gbitmapn; bi++)
+ if (!Gbitmaps[bi].inuse)
+ goto found;
+
+ Gbitmaps = Marraygrow(Gbitmaps,
+ (long) (Gbitmapn + BITMAPINCR) * BITMAPSIZE);
+ for (bi = Gbitmapn; bi < Gbitmapn + BITMAPINCR; bi++)
+ Gbitmaps[bi].inuse = FALSE;
+ bi = Gbitmapn, Gbitmapn += BITMAPINCR;
+
+ found:
+ new = &Gbitmaps[bi];
+ return new;
+}
+
+void Gerr(char *file, int line, int errnum, ...)
+{
+ va_list args;
+
+#ifdef FEATURE_WIN32
+ char buf[256];
+
+ Gerrno = errnum;
+ if (!warnflag)
+ return;
+
+ va_start(args, errnum);
+ vsprintf(buf, errmsg[errnum], args);
+ Gnocallbacks = TRUE;
+ MessageBox((HWND) NULL, buf, "Lefty Warning", MB_APPLMODAL);
+ Gnocallbacks = FALSE;
+ va_end(args);
+#else
+ Gerrno = errnum;
+ if (!Gerrflag)
+ return;
+
+ va_start(args, errnum);
+ fprintf(stderr, "warning: (file %s, line %d) ", file, line);
+ vfprintf(stderr, errmsg[errnum], args);
+ fprintf(stderr, "\n");
+ va_end(args);
+#endif
+}
+
+static int unpackstring(char *s)
+{
+ char *p1, *p2;
+ int n;
+
+ if ((n = strlen(s) + 1) > textn)
+ textn = n, texts = Marraygrow(texts, (long) textn);
+ strcpy(texts, s);
+ n = 0;
+ p1 = p2 = texts;
+ tlarray[0].p = p1;
+ while (*p1) {
+ if (p1[0] == '\\') {
+ if (p1[1] == 'n' || p1[1] == 'l' || p1[1] == 'r') {
+ tlarray[n].n = p1 - tlarray[n].p;
+ tlarray[n].j = p1[1];
+ tlarray[++n].p = (p1 += 2);
+ } else {
+ for (p2 = p1 + 1; *p2; p2++)
+ p2[-1] = p2[0];
+ p2[-1] = 0;
+ p1++;
+ }
+ } else
+ p1++;
+ }
+ if ((tlarray[n].n = p1 - tlarray[n].p) > 0)
+ tlarray[n++].j = 'n';
+ return n;
+}
--- /dev/null
+/* $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 _G_H
+#define _G_H
+#ifdef FEATURE_X11
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/cursorfont.h>
+#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/Text.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/SmeBSB.h>
+#include <X11/Xmu/CurUtil.h>
+#ifdef FEATURE_GMAP
+#ifdef FEATURE_MESAGL
+#include <GL/GLwDrawA.h>
+#else
+#include <X11/GLw/GLwDrawA.h>
+#endif
+#include <Performer/pf.h>
+#endif
+#endif
+
+#ifdef FEATURE_GTK
+#include <gtk/gtk.h>
+#ifdef FEATURE_GMAP
+#ifdef FEATURE_MESAGL
+#include <GL/GLwDrawA.h>
+#endif
+#include <Performer/pf.h>
+#endif
+#endif
+
+
+/* general coordinate structures */
+
+ typedef struct Gxy_t {
+ double x, y;
+ } Gxy_t;
+ typedef Gxy_t Gpoint_t;
+ typedef Gxy_t Gsize_t;
+ typedef struct Grect_t {
+ Gxy_t o, c;
+ } Grect_t;
+
+/* textline structure */
+ typedef struct Gtextline_t {
+ char *p;
+ int n, j;
+ int w, h;
+ } Gtextline_t;
+
+/* Color structure */
+
+ typedef struct Gcolor_t {
+ int index;
+ int r, g, b;
+ } Gcolor_t;
+#define G_MAXCOLORS 256
+
+/* event structures */
+
+/* event consumption modes */
+ typedef enum {
+ G_ONEEVENT, G_MANYEVENTS
+ } Geventmode_t;
+
+/* event types and main structure */
+ typedef enum {
+ G_MOUSE, G_KEYBD
+ } Getype_t;
+#define G_DOWN 0
+#define G_UP 1
+#define G_MOVE 2
+#define G_LEFT 0
+#define G_MIDDLE 1
+#define G_RIGHT 2
+ typedef struct Gevent_t {
+ Getype_t type;
+ int wi;
+ int code;
+ int data;
+ Gpoint_t p;
+ } Gevent_t;
+
+/* Widgets */
+
+/* minimum widget sizes */
+#define MINVWSIZE 100
+#define MINTWSIZE 40
+#define MINBWSIZE 40
+#define MINLWSIZE 25
+#define MINAWSIZE 25
+#define MINSWSIZE 40
+#define MINCWSIZE 100
+#define MINPWSIZE 100
+
+/* gfx attributes for the [p]canvas widget */
+
+/* drawing styles */
+#define G_SOLID 0
+#define G_DASHED 1
+#define G_DOTTED 2
+#define G_LONGDASHED 3
+#define G_SHORTDASHED 4
+
+/* drawing modes */
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+#define G_SRC GDK_COPY
+#define G_XOR GDK_XOR
+#else
+#define G_SRC GXcopy
+#define G_XOR GXxor
+#endif
+#else
+#ifdef FEATURE_WIN32
+#define G_SRC R2_COPYPEN
+#define G_XOR R2_NOT
+#else
+#define G_SRC 0
+#define G_XOR 1
+#endif
+#endif
+
+/* gfx attributes and the attribute structure */
+ typedef enum {
+ G_GATTRCOLOR = 1, G_GATTRWIDTH = 2, G_GATTRMODE = 4,
+ G_GATTRFILL = 8, G_GATTRSTYLE = 16
+ } Ggattrflags_t;
+ typedef struct Ggattr_t {
+ Ggattrflags_t flags;
+ int color;
+ int width;
+ int mode;
+ int fill;
+ int style;
+ } Ggattr_t;
+
+/* widget attributes structures */
+
+ typedef enum {
+ G_ATTRTYPEINT, G_ATTRTYPELONG,
+ G_ATTRTYPEFLOAT, G_ATTRTYPEDOUBLE,
+ G_ATTRTYPETEXT,
+ G_ATTRTYPEPOINT, G_ATTRTYPESIZE, G_ATTRTYPERECT,
+ G_ATTRTYPECOLOR,
+ G_ATTRTYPEFUNC,
+ G_ATTRTYPEULONG
+ } Gwattrtype_t;
+ typedef struct Gwattrmap_t {
+ int id;
+ Gwattrtype_t type;
+ char *name;
+ } Gwattrmap_t;
+ typedef struct Gwattr_t {
+ int id;
+ union {
+ int i;
+ long l;
+ float f;
+ double d;
+ char *t;
+ Gpoint_t p;
+ Gsize_t s;
+ Grect_t r;
+ Gcolor_t c;
+ void *func;
+ unsigned long u;
+ } u;
+ } Gwattr_t;
+ typedef struct Gwlist_t {
+ int wid;
+ char *wname;
+ int *attrid;
+ } Gwlist_t;
+
+/* attribute ids */
+#define G_ATTRORIGIN 0
+#define G_ATTRSIZE 1
+#define G_ATTRBORDERWIDTH 2
+#define G_ATTRNAME 3
+#define G_ATTRTEXT 4
+#define G_ATTRAPPENDTEXT 5
+#define G_ATTRSELECTION 6
+#define G_ATTRCURSOR 7
+#define G_ATTRMODE 8
+#define G_ATTRLAYOUT 9
+#define G_ATTRZORDER 10
+#define G_ATTRCOLOR 11
+#define G_ATTRVIEWPORT 12
+#define G_ATTRWINDOW 13
+#define G_ATTRWINDOWID 14
+#define G_ATTRCHILDCENTER 15
+#define G_ATTRNEWLINECB 16
+#define G_ATTRRESIZECB 17
+#define G_ATTRBUTTONCB 18
+#define G_ATTREVENTCB 19
+#define G_ATTRUSERDATA 20
+
+/* array widget structs */
+ typedef struct Gawcarray_t {
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+ GtkWidget *w;
+#else
+ Widget w;
+#endif
+#else
+#ifdef FEATURE_WIN32
+ HWND w;
+#else
+ int w;
+#endif
+#endif
+ int flag;
+ int ox, oy, sx, sy, bs;
+ } Gawcarray_t;
+#define AWCARRAYINCR 10
+#define AWCARRAYSIZE sizeof (Gawcarray_t)
+
+#define G_AWHARRAY 1
+#define G_AWVARRAY 2
+ typedef struct Gawdata_t {
+ int type;
+ int sx, sy;
+ Gawcarray_t *carray;
+ int cj, cn;
+#ifdef FEATURE_WIN32
+ int batchmode, working;
+#endif
+ } Gawdata_t;
+
+/* query widget macros */
+#define G_QWSTRING 1 /* string query */
+#define G_QWFILE 2 /* file query */
+#define G_QWCHOICE 3 /* choose 1 query */
+#define G_QWMODES 3 /* total number of modes */
+
+/* widget callbacks */
+ typedef void (*Gtwnewlinecb) (int, char *);
+ typedef void (*Gbuttoncb) (int, void *);
+ typedef void (*Glabelcb) (Gevent_t *);
+ typedef void (*Gcanvascb) (Gevent_t *);
+ typedef void (*Gawordercb) (void *, Gawdata_t *);
+ typedef void (*Gawcoordscb) (int, Gawdata_t *);
+ typedef void (*Gviewcb) (Gevent_t *);
+
+#define G_ARRAYWIDGET 0
+#define G_BUTTONWIDGET 1
+#define G_CANVASWIDGET 2
+#define G_LABELWIDGET 3
+#define G_MENUWIDGET 4
+#define G_PCANVASWIDGET 5
+#define G_QUERYWIDGET 6
+#define G_SCROLLWIDGET 7
+#define G_TEXTWIDGET 8
+#define G_VIEWWIDGET 9
+#define G_WTYPESIZE 10
+
+/* predefined widgets */
+
+/* --- array --- */
+ typedef struct Gaw_t {
+ Gawcoordscb func;
+ int mode;
+#ifdef FEATURE_WIN32
+ Gawdata_t data;
+#endif
+ } Gaw_t;
+#define AWSIZE sizeof (Gaw_t)
+
+/* --- button --- */
+ typedef struct Gbw_t {
+ Gbuttoncb func;
+ } Gbw_t;
+#define BWSIZE sizeof (Gbw_t)
+
+/* --- canvas --- */
+ typedef struct Gcw_t {
+ int needredraw;
+ int buttonsdown;
+ char bstate[3];
+ struct Gcwcolor_t {
+ int inuse;
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+ GdkColor color;
+#else
+ XColor color;
+#endif
+#else
+#ifdef FEATURE_WIN32
+ PALETTEENTRY color;
+#endif
+#endif
+ } colors[G_MAXCOLORS];
+ char allocedcolor[2];
+ Ggattr_t gattr, defgattr;
+ Grect_t wrect;
+ Gsize_t vsize;
+ Grect_t clip;
+ Gcanvascb func;
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+ GtkWindow window;
+ GdkColormap *cmap;
+ GdkGC *gc;
+ GdkPixmap grays[17];
+ GdkFont *font;
+#else
+ Window window;
+ Colormap cmap;
+ GC gc;
+ Pixmap grays[17];
+ XFontStruct *font;
+#endif
+#else
+#ifdef FEATURE_WIN32
+ HPALETTE cmap;
+ HDC gc;
+ HBRUSH grays[17];
+ HFONT font;
+ int ncolor;
+#endif
+#endif
+#ifdef FEATURE_GMAP
+ int gmapmode;
+#endif
+ } Gcw_t;
+#define CWSIZE sizeof (Gcw_t)
+
+/* --- label --- */
+ typedef struct Glw_t {
+ Glabelcb func;
+ } Glw_t;
+#define LWSIZE sizeof (Glw_t)
+
+/* --- menu --- */
+ typedef struct Gmw_t {
+#ifdef FEATURE_GTK
+ glong count;
+#else
+ long count;
+#endif
+ } Gmw_t;
+#define MWSIZE sizeof (Gmw_t)
+
+/* --- postscript --- */
+ typedef struct Gpw_t {
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+ FILE *fp;
+ struct Gpwcolor_t {
+ int inuse;
+ int r, g, b;
+ double nr, ng, nb;
+ } colors[G_MAXCOLORS];
+ Ggattr_t gattr, defgattr;
+ Grect_t wrect;
+ Gsize_t vsize;
+#else
+#ifdef FEATURE_WIN32
+ struct Gpwcolor_t {
+ int inuse;
+ PALETTEENTRY color;
+ } colors[G_MAXCOLORS];
+ Ggattr_t gattr, defgattr;
+ Grect_t wrect;
+ Gsize_t vsize;
+ HPALETTE cmap;
+ HDC gc;
+ HBRUSH grays[17];
+ HFONT font;
+ int ncolor, mode;
+#else
+ int dummy;
+#endif
+#endif
+ } Gpw_t;
+#define PWSIZE sizeof (Gpw_t)
+
+/* --- query --- */
+ typedef struct Gqw_t {
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+ GtkWidget *w;
+#else
+ Widget w;
+#endif
+#else
+#ifdef FEATURE_WIN32
+ HWND w;
+#endif
+#endif
+ int mode;
+ int state, button;
+ } Gqw_t;
+#define QWSIZE sizeof (Gqw_t)
+
+/* --- scroll --- */
+ typedef struct Gsw_t {
+ int dummy;
+ } Gsw_t;
+#define SWSIZE sizeof (Gsw_t)
+
+/* --- text --- */
+ typedef struct Gtw_t {
+ Gtwnewlinecb func;
+ } Gtw_t;
+#define TWSIZE sizeof (Gtw_t)
+
+/* --- view --- */
+ typedef struct Gvw_t {
+ Gviewcb func;
+ int closing;
+ } Gvw_t;
+#define VWSIZE sizeof (Gvw_t)
+
+/* the main widget structure */
+ typedef struct Gwidget_t {
+ int type;
+ int inuse;
+ int pwi;
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+ GtkWidget *w;
+#else
+ Widget w;
+#endif
+#else
+#ifdef FEATURE_WIN32
+ HWND w;
+#else
+ int w;
+#endif
+#endif
+ union {
+ Gaw_t *a;
+ Gbw_t *b;
+ Gcw_t *c;
+ Glw_t *l;
+ Gmw_t *m;
+ Gpw_t *p;
+ Gqw_t *q;
+ Gsw_t *s;
+ Gtw_t *t;
+ Gvw_t *v;
+ } u;
+ unsigned long udata;
+ } Gwidget_t;
+#define WIDGETINCR 20
+#define WIDGETSIZE sizeof (Gwidget_t)
+
+/* bitmap data structure */
+ typedef struct Gbitmap_t {
+ int inuse;
+ int canvas;
+ int ctype; /* type of canvas, eg. G_CANVASWIDGET */
+ Gsize_t size;
+ Gsize_t scale;
+ union {
+ struct {
+#if defined(FEATURE_X11) || defined(FEATURE_GTK)
+#ifdef FEATURE_GTK
+ GdkPixmap orig, scaled;
+#else
+ Pixmap orig, scaled;
+#endif
+#else
+#ifdef FEATURE_WIN32
+ HBITMAP orig, scaled;
+#else
+ int dummy;
+#endif
+#endif
+ } bmap;
+ unsigned char *bits;
+ } u;
+ } Gbitmap_t;
+
+ extern Gbitmap_t *Gbitmaps;
+ extern int Gbitmapn;
+
+/* global array of widgets */
+ extern Gwidget_t *Gwidgets;
+ extern int Gwidgetn;
+
+ extern Gwlist_t Gwlist[];
+ extern Gwattrmap_t Gwattrmap[];
+
+ extern char *Gdefaultfont;
+ extern int Gneedredraw;
+ extern int Gbuttonsdown;
+ extern int Gerrflag;
+ extern char *Gpscanvasname;
+
+ extern int Gxfd;
+
+#ifdef FEATURE_GTK
+ static int Gnocallbacks;
+#else
+#ifdef FEATURE_WIN32
+ extern int Gnocallbacks;
+#endif
+#endif
+
+/* functions returning an int
+ return -1 if there's an error and
+ also set the Gerrno variable
+
+ the rendering functions may return +1
+ if the graphical object is completely hidden
+*/
+ int Ginit(void);
+ int Gterm(void);
+ int Gcreatewidget(int, int, int, Gwattr_t *);
+ int Gsetwidgetattr(int, int, Gwattr_t *);
+ int Ggetwidgetattr(int, int, Gwattr_t *);
+ int Gdestroywidget(int);
+ int Gqueryask(int, char *, char *, char *, int);
+ int Gmenuaddentries(int, int, char **);
+ int Gmenudisplay(int, int);
+ int Gsync(void);
+ int Gresetbstate(int);
+ int Gcanvasclear(int);
+ int Gsetgfxattr(int, Ggattr_t *);
+ int Ggetgfxattr(int, Ggattr_t *);
+ int Garrow(int, Gpoint_t, Gpoint_t, Ggattr_t *);
+ int Gline(int, Gpoint_t, Gpoint_t, Ggattr_t *);
+ int Gbox(int, Grect_t, Ggattr_t *);
+ int Gpolygon(int, int, Gpoint_t *, Ggattr_t *);
+ int Gsplinegon(int, int, Gpoint_t *, Ggattr_t *);
+ int Garc(int, Gpoint_t, Gsize_t, double, double, Ggattr_t *);
+ int Gtext(int, char *, Gpoint_t, char *, double, char *, Ggattr_t *);
+ int Ggettextsize(int, char *, char *, double, Gsize_t *);
+ int Gcreatebitmap(int, Gsize_t);
+ int Gdestroybitmap(int);
+ int Greadbitmap(int, FILE *);
+ int Gwritebitmap(FILE *, int);
+ int Gbitblt(int, Gpoint_t, Grect_t, int, char *, Ggattr_t *);
+ int Ggetmousecoords(int, Gpoint_t *, int *);
+
+ int Gprocessevents(int, Geventmode_t);
+
+ int Gaworder(Gwidget_t *, void *, Gawordercb);
+ int Gawsetmode(Gwidget_t *, int);
+ int Gawgetmode(Gwidget_t *);
+ void Gawdefcoordscb(int, Gawdata_t *);
+
+ Gwidget_t *newwidget(int);
+ Gwidget_t *findwidget(unsigned long, int);
+ Gbitmap_t *newbitmap(void);
+ void Gerr(char *, int, int, ...);
+
+/* error messages */
+#define G_ERRBADATTRID 1
+#define G_ERRBADATTRVALUE 2
+#define G_ERRBADCOLORINDEX 3
+#define G_ERRBADPARENTWIDGETID 4
+#define G_ERRBADWIDGETID 5
+#define G_ERRBADWIDGETTYPE 6
+#define G_ERRCANNOTCREATEWIDGET 7
+#define G_ERRCANNOTGETATTR 8
+#define G_ERRCANNOTOPENFILE 9
+#define G_ERRCANNOTSETATTR1 10
+#define G_ERRCANNOTSETATTR2 11
+#define G_ERRINITFAILED 12
+#define G_ERRNOCHILDWIDGET 13
+#define G_ERRNOPARENTWIDGET 14
+#define G_ERRNOSUCHCURSOR 15
+#define G_ERRNOTACANVAS 16
+#define G_ERRNOTIMPLEMENTED 17
+#define G_ERRNOTSUPPORTED 18
+#define G_ERRBADBITMAPID 19
+#define G_ERRCANNOTCREATEBITMAP 20
+#define G_ERRNOBITMAP 21
+#define G_ERRCANNOTREADBITMAP 22
+
+ extern int Gerrno;
+#endif /* _G_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* $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 "g.h"
+#include "mem.h"
+#include "io.h"
+#include "code.h"
+#include "tbl.h"
+#include "parse.h"
+#include "exec.h"
+#include "gfxview.h"
+
+#define max(a, b) (((a) >= (b)) ? (a) : (b))
+#define min(a, b) (((a) >= (b)) ? (b) : (a))
+
+#define getwintnset(to) \
+ if (getint (to, &wattrp[wattri].u.i) != -1) wattri++;
+#define getwpointnset(to) \
+ if (getxy (to, &wattrp[wattri].u.p) != -1) wattri++;
+#define getwsizenset(to) \
+ if (getxy (to, &wattrp[wattri].u.s) != -1) wattri++;
+#define getwrectnset(to) \
+ if (getrect (to, &wattrp[wattri].u.r) != -1) wattri++;
+#define getwstrnset(to) \
+ if (getstr (to, &wattrp[wattri].u.t) != -1) wattri++;
+#define getwcolornset(ko, vo) \
+ if (getcolor (ko, vo, &wattrp[wattri].u.c) != -1) wattri++;
+
+#define getaintnset(to, n, flag) \
+ if (to) { \
+ getint (to, &n), dp->flags |= flag; \
+ }
+#define getastrnset(to, s, flag) \
+ if (to) \
+ getstr (to, &s), dp->flags |= flag;
+
+typedef struct colorname_t {
+ char *name;
+ unsigned char r, g, b;
+} colorname_t;
+
+#include "colors.txt"
+
+typedef struct gfxrect_t {
+ struct gfxrect_t *next;
+ Tobj ko;
+ Grect_t r;
+} gfxrect_t;
+typedef struct gfxmenu_t {
+ struct gfxmenu_t *next;
+ Tobj ko;
+ long time;
+ int mi;
+} gfxmenu_t;
+#define LISTSIZE 100
+typedef struct gfxnode_t {
+ int inuse;
+ int wi;
+ Tobj plvo, pmvo, prvo, pkvo[256];
+ Gpoint_t plp, pmp, prp, pkp[256];
+ char ls, ms, rs, ks[256];
+ struct gfxrect_t *rect[LISTSIZE];
+ struct gfxmenu_t *menu[LISTSIZE];
+} gfxnode_t;
+#define GFXNODEINCR 20
+#define GFXNODESIZE sizeof (gfxnode_t)
+static gfxnode_t *gfxnodes;
+static int gfxnoden;
+
+#define ISAWIDGET(wi) (wi >= 0 && wi < Gwidgetn && Gwidgets[wi].inuse)
+#define ISALABEL(wi) (Gwidgets[wi].type == G_LABELWIDGET)
+#define ISACANVAS(wi) (Gwidgets[wi].type == G_CANVASWIDGET)
+#define ISACANVAS2(wi) (Gwidgets[wi].type == G_CANVASWIDGET || \
+ Gwidgets[wi].type == G_PCANVASWIDGET)
+#define NODEID(wi) Gwidgets[wi].udata
+#define ISABITMAP(bi) (bi >= 0 && bi < Gbitmapn && Gbitmaps[bi].inuse)
+
+static Gpoint_t *gpp = NULL;
+static long gpn = 0;
+#define GPINCR 100
+#define GPSIZE sizeof (Gpoint_t)
+
+static Gwattr_t *wattrp = NULL;
+static int wattrn = 0;
+static int wattri = 0;
+#define WATTRINCR 10
+#define WATTRSIZE sizeof (Gwattr_t)
+
+static Tobj rootwo, rootbo;
+
+static void nodeinit(int);
+static void nodeterm(int);
+static void rectinit(int);
+static void rectterm(int);
+static void rectinsert(int, Tobj, Grect_t);
+static void rectmerge(int, Tobj, Grect_t);
+static Tobj rectfind(int, Gpoint_t);
+static void rectdelete(int, Tobj);
+static void rectprune(int);
+static void menuinsert(int, Tobj, long, int);
+static int menufind(int, Tobj, long);
+static void menuprune(int);
+static int getwattr(Tobj, int *);
+static int getgattr(Tobj, Ggattr_t *);
+static int getrect(Tobj, Grect_t *);
+static int getxy(Tobj, Gxy_t *);
+static int getint(Tobj, int *);
+static int getdouble(Tobj, double *);
+static int getstr(Tobj, char **);
+static int getcolor(Tobj, Tobj, Gcolor_t *);
+
+void GFXinit(void)
+{
+ int ni;
+
+ Tinss(root, "widgets", (rootwo = Ttable(100)));
+ Tinss(root, "bitmaps", (rootbo = Ttable(100)));
+ gfxnodes = Marrayalloc((long) GFXNODEINCR * GFXNODESIZE);
+ gfxnoden = GFXNODEINCR;
+ for (ni = 0; ni < gfxnoden; ni++)
+ gfxnodes[ni].inuse = FALSE;
+ ni = 0;
+ gpp = Marrayalloc((long) GPINCR * GPSIZE);
+ gpn = GPINCR;
+ wattrp = Marrayalloc((long) WATTRINCR * WATTRSIZE);
+ wattrn = WATTRINCR, wattri = 0;
+}
+
+void GFXterm(void)
+{
+ int ni;
+
+ Marrayfree(wattrp), wattrp = NULL, wattrn = 0;
+ Marrayfree(gpp), gpp = NULL, gpn = 0;
+ for (ni = 0; ni < gfxnoden; ni++) {
+ if (gfxnodes[ni].inuse) {
+ Gdestroywidget(gfxnodes[ni].wi);
+ nodeterm(ni);
+ gfxnodes[ni].inuse = FALSE;
+ }
+ }
+ Marrayfree(gfxnodes), gfxnodes = NULL, gfxnoden = 0;
+ Tdels(root, "bitmaps");
+ Tdels(root, "widgets");
+}
+
+/* callback for mem.c module - removes dead objects from gfxnodes */
+void GFXprune(void)
+{
+ gfxnode_t *np;
+ int ni, ki;
+
+ for (ni = 0; ni < gfxnoden; ni++) {
+ np = &gfxnodes[ni];
+ if (np->inuse) {
+ rectprune(ni), menuprune(ni);
+ if (np->plvo && !M_AREAOF(np->plvo))
+ np->plvo = 0;
+ if (np->pmvo && !M_AREAOF(np->pmvo))
+ np->pmvo = 0;
+ if (np->prvo && !M_AREAOF(np->prvo))
+ np->prvo = 0;
+ for (ki = 0; ki < 256; ki++)
+ if (np->pkvo[ki] && !M_AREAOF(np->pkvo[ki]))
+ np->pkvo[ki] = 0;
+ }
+ }
+}
+
+/* callback for g.c module - calls the appropriate lefty function */
+void GFXlabelcb(Gevent_t * evp)
+{
+ Tobj fo, to, co, wo;
+ char *fn;
+ char s[2];
+ long fm;
+ fn = 0;
+
+ wo = Tfindi(rootwo, evp->wi);
+ switch (evp->type) {
+ case G_MOUSE:
+ switch (evp->data) {
+ case G_LEFT:
+ fn = (evp->code == G_UP) ? "leftup" : "leftdown";
+ break;
+ case G_MIDDLE:
+ fn = (evp->code == G_UP) ? "middleup" : "middledown";
+ break;
+ case G_RIGHT:
+ fn = (evp->code == G_UP) ? "rightup" : "rightdown";
+ break;
+ }
+ break;
+ case G_KEYBD:
+ fn = (evp->code == G_UP) ? "keyup" : "keydown";
+ break;
+ }
+ if (!wo || !(fo = Tfinds(wo, fn)) || Tgettype(fo) != T_CODE)
+ if (!(fo = Tfinds(root, fn)) || Tgettype(fo) != T_CODE)
+ return;
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(evp->wi));
+ if (evp->type == G_KEYBD)
+ s[0] = evp->data, s[1] = '\000', Tinss(to, "key", Tstring(s));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+}
+
+/* callback for g.c module - calls the appropriate lefty function */
+void GFXviewcb(Gevent_t * evp)
+{
+ Tobj fo, to, co, wo;
+ char *fn;
+ long fm;
+
+ wo = Tfindi(rootwo, evp->wi);
+ fn = "closeview";
+ if (!wo || !(fo = Tfinds(wo, fn)) || Tgettype(fo) != T_CODE)
+ if (!(fo = Tfinds(root, fn)) || Tgettype(fo) != T_CODE)
+ exit(0);
+ fm = Mpushmark(fo);
+ to = Ttable(2);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(evp->wi));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+}
+
+/* callback for g.c module - calls the appropriate lefty function */
+void GFXevent(Gevent_t * evp)
+{
+ Tobj vo, pvo = NULL, fo, to, po, co, wo;
+ gfxnode_t *np;
+ Gpoint_t pp = { 0, 0 };
+ char *fn;
+ char s[2];
+ long fm;
+ int ni;
+ fn = 0;
+
+ ni = Gwidgets[evp->wi].udata;
+ np = &gfxnodes[ni];
+ wo = Tfindi(rootwo, evp->wi);
+ if (!(vo = rectfind(ni, evp->p)))
+ vo = null;
+ switch (evp->type) {
+ case G_MOUSE:
+ switch (evp->data) {
+ case G_LEFT:
+ if (evp->code == G_UP)
+ fn = "leftup", pvo = np->plvo, pp = np->plp, np->ls = 0;
+ else
+ fn = "leftdown", np->plvo = vo, np->plp = evp->p, np->ls =
+ 1;
+ break;
+ case G_MIDDLE:
+ if (evp->code == G_UP)
+ fn = "middleup", pvo = np->pmvo, pp = np->pmp, np->ms = 0;
+ else
+ fn = "middledown", np->pmvo = vo, np->pmp =
+ evp->p, np->ms = 1;
+ break;
+ case G_RIGHT:
+ if (evp->code == G_UP)
+ fn = "rightup", pvo = np->prvo, pp = np->prp, np->rs = 0;
+ else
+ fn = "rightdown", np->prvo = vo, np->prp = evp->p, np->rs =
+ 1;
+ break;
+ }
+ break;
+ case G_KEYBD:
+ if (evp->code == G_UP) {
+ fn = "keyup";
+ pvo = np->pkvo[evp->data];
+ pp = np->pkp[evp->data];
+ np->ks[evp->data] = 0;
+ } else {
+ fn = "keydown";
+ np->pkvo[evp->data] = vo;
+ np->pkp[evp->data] = evp->p;
+ np->ks[evp->data] = 1;
+ }
+ break;
+ }
+ if (!wo || !(fo = Tfinds(wo, fn)) || Tgettype(fo) != T_CODE)
+ if (!(fo = Tfinds(root, fn)) || Tgettype(fo) != T_CODE)
+ return;
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(evp->wi));
+ Tinss(to, "obj", vo);
+ Tinss(to, "pos", (po = Ttable(2)));
+ Tinss(po, "x", Treal(evp->p.x));
+ Tinss(po, "y", Treal(evp->p.y));
+ if (evp->code == G_UP) {
+ Tinss(to, "pobj", pvo);
+ Tinss(to, "ppos", (po = Ttable(2)));
+ Tinss(po, "x", Treal(pp.x));
+ Tinss(po, "y", Treal(pp.y));
+ }
+ if (evp->type == G_KEYBD)
+ s[0] = evp->data, s[1] = '\000', Tinss(to, "key", Tstring(s));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+}
+
+/* called directly from lefty.c, when any button is held down */
+void GFXmove(void)
+{
+ gfxnode_t *np;
+ char *fn[3];
+ Tobj vo[3], fo, to, po, co, wo;
+ Gpoint_t cp, pp[3];
+ long fm;
+ int count, i, ni;
+
+ for (ni = 0; ni < gfxnoden; ni++) {
+ np = &gfxnodes[ni];
+ if (!np->inuse || !ISACANVAS(np->wi) ||
+ !Gwidgets[np->wi].u.c->buttonsdown)
+ continue;
+ wo = Tfindi(rootwo, np->wi);
+ Ggetmousecoords(np->wi, &cp, &count);
+ if (!count) {
+ Gresetbstate(np->wi);
+ continue;
+ }
+ if (np->ls)
+ fn[0] = "leftmove", pp[0] = np->plp, vo[0] = np->plvo;
+ else
+ fn[0] = NULL;
+ if (np->ms)
+ fn[1] = "middlemove", pp[1] = np->pmp, vo[1] = np->pmvo;
+ else
+ fn[1] = NULL;
+ if (np->rs)
+ fn[2] = "rightmove", pp[2] = np->prp, vo[2] = np->prvo;
+ else
+ fn[2] = NULL;
+ for (i = 0; i < 3; i++) {
+ if (!fn[i])
+ continue;
+ if (!wo || !(fo = Tfinds(wo, fn[i])) || Tgettype(fo) != T_CODE)
+ fo = Tfinds(root, fn[i]);
+ if (fo && Tgettype(fo) == T_CODE) {
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(np->wi));
+ Tinss(to, "obj", vo[i]);
+ Tinss(to, "pos", (po = Ttable(2)));
+ Tinss(po, "x", Treal(cp.x));
+ Tinss(po, "y", Treal(cp.y));
+ Tinss(to, "ppos", (po = Ttable(2)));
+ Tinss(po, "x", Treal(pp[i].x));
+ Tinss(po, "y", Treal(pp[i].y));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+ }
+ }
+ }
+}
+
+/* called directly from lefty.c, when any canvas needs to be redrawn */
+void GFXredraw(void)
+{
+ gfxnode_t *np;
+ Tobj wo, fo, co, to;
+ long fm;
+ int ni;
+
+ for (ni = 0; ni < gfxnoden; ni++) {
+ np = &gfxnodes[ni];
+ if (!np->inuse || !ISACANVAS(np->wi) ||
+ !Gwidgets[np->wi].u.c->needredraw)
+ continue;
+ Gwidgets[np->wi].u.c->needredraw = FALSE;
+ wo = Tfindi(rootwo, np->wi);
+ if (!wo || !(fo = Tfinds(wo, "redraw")) || Tgettype(fo) != T_CODE)
+ if (!(fo = Tfinds(root, "redraw")) || Tgettype(fo) != T_CODE)
+ return;
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(np->wi));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+ }
+}
+
+void GFXtextcb(int wi, char *s)
+{
+ Tobj wo, fo, co, to;
+ long fm;
+
+ if (!(wo = Tfindi(rootwo, wi)))
+ return;
+
+ if (!(fo = Tfinds(wo, "oneline")) || Tgettype(fo) != T_CODE)
+ return;
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(wi));
+ Tinss(to, "text", Tstring(s));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+}
+
+void GFXbuttoncb(int wi, void *data)
+{
+ Tobj wo, fo, co, to;
+ long fm;
+
+ if (!(wo = Tfindi(rootwo, wi)))
+ return;
+
+ if (!(fo = Tfinds(wo, "pressed")) || Tgettype(fo) != T_CODE)
+ return;
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(wi));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(fm);
+}
+
+void GFXarrayresizecb(int wi, Gawdata_t * dp)
+{
+ Tobj wo, fo, co, so, to, lrtno = NULL, sxo, syo;
+ Tkvindex_t tkvi;
+ Gawcarray_t *cp;
+ int sx, sy, csx, csy, ci;
+ long fm;
+
+ if (!(wo = Tfindi(rootwo, wi)))
+ return;
+
+ if (!(fo = Tfinds(wo, "resize")) || Tgettype(fo) != T_CODE) {
+ Gawdefcoordscb(wi, dp);
+ return;
+ }
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ Mpushmark(to);
+ Tinss(to, "widget", Tinteger(wi));
+ Tinss(to, "size", (so = Ttable(2)));
+ Tinss(so, "x", Treal((double) dp->sx));
+ Tinss(so, "y", Treal((double) dp->sy));
+ if ((co = Pfcall(fo, to)))
+ lrtno = Eunit(co);
+ Mpopmark(fm);
+ if (!lrtno) {
+ Gawdefcoordscb(wi, dp);
+ return;
+ }
+ for (Tgetfirst(lrtno, &tkvi); tkvi.kvp; Tgetnext(&tkvi)) {
+ if (!T_ISNUMBER(tkvi.kvp->ko) || !T_ISTABLE((so = tkvi.kvp->vo)))
+ continue;
+ wi = Tgetnumber(tkvi.kvp->ko);
+ if (!ISAWIDGET(wi))
+ continue;
+ for (ci = 0; ci < dp->cj; ci++) {
+ cp = &dp->carray[ci];
+ if (!cp->flag || cp->w != Gwidgets[wi].w)
+ continue;
+ if ((sxo = Tfinds(so, "x")) && T_ISNUMBER(sxo))
+ cp->sx = Tgetnumber(sxo);
+ if ((syo = Tfinds(so, "y")) && T_ISNUMBER(syo))
+ cp->sy = Tgetnumber(syo);
+ break;
+ }
+ }
+ sx = dp->sx, sy = dp->sy;
+ csx = csy = 0;
+ for (ci = 0; ci < dp->cj; ci++) {
+ cp = &dp->carray[ci];
+ if (!cp->flag)
+ continue;
+ cp->ox = csx, cp->oy = csy;
+ if (dp->type == G_AWVARRAY)
+ cp->sx = sx - 2 * cp->bs, csy += cp->sy + 2 * cp->bs;
+ else
+ cp->sy = sy - 2 * cp->bs, csx += cp->sx + 2 * cp->bs;
+ }
+ if (dp->type == G_AWVARRAY)
+ dp->sy = csy;
+ else
+ dp->sx = csx;
+}
+
+/* callback for when there is input on some file descriptor */
+void GFXmonitorfile(int fd)
+{
+ Tobj fo, to, co;
+ long fm, tm;
+
+ if (!(fo = Tfinds(root, "monitorfile")) || Tgettype(fo) != T_CODE)
+ return;
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ tm = Mpushmark(to);
+ Tinss(to, "fd", Tinteger(fd));
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(tm);
+ Mpopmark(fm);
+}
+
+/* callback for when there is no X event and no file input */
+void GFXidle(void)
+{
+ Tobj fo, to, co;
+ long fm, tm;
+
+ if (!(fo = Tfinds(root, "idle")) || Tgettype(fo) != T_CODE)
+ return;
+
+ fm = Mpushmark(fo);
+ to = Ttable(4);
+ tm = Mpushmark(to);
+ if ((co = Pfcall(fo, to)))
+ Eunit(co);
+ Mpopmark(tm);
+ Mpopmark(fm);
+}
+
+/* LEFTY builtin */
+int GFXcreatewidget(int argc, lvar_t * argv)
+{
+ Tobj pwo, cwo, cho;
+ long rtnm;
+ int type, pwi, wi, ni;
+
+ type = -1;
+ if (getint(argv[0].o, &pwi) == -1 || getwattr(argv[1].o, &type) == -1)
+ return L_FAILURE;
+ if (type != G_VIEWWIDGET && type != G_PCANVASWIDGET && !ISAWIDGET(pwi))
+ return L_FAILURE;
+ if (type == G_CANVASWIDGET || type == G_LABELWIDGET) {
+ for (ni = 0; ni < gfxnoden; ni++)
+ if (!gfxnodes[ni].inuse)
+ break;
+ if (ni == gfxnoden) {
+ gfxnodes = Marraygrow(gfxnodes,
+ (long) (ni + GFXNODEINCR) * GFXNODESIZE);
+ for (ni = gfxnoden; ni < gfxnoden + GFXNODEINCR; ni++)
+ gfxnodes[ni].inuse = FALSE;
+ ni = gfxnoden, gfxnoden += GFXNODEINCR;
+ }
+ nodeinit(ni);
+ if (wattri >= wattrn) {
+ wattrp = Marraygrow(wattrp,
+ (long) (wattrn + WATTRINCR) * WATTRSIZE);
+ wattrn += WATTRINCR;
+ }
+ switch (type) {
+ case G_CANVASWIDGET:
+ wattrp[wattri].id = G_ATTRUSERDATA;
+ wattrp[wattri].u.u = ni, wattri++;
+ break;
+ case G_LABELWIDGET:
+ wattrp[wattri].id = G_ATTRUSERDATA;
+ wattrp[wattri].u.u = ni, wattri++;
+ break;
+ }
+ wi = gfxnodes[ni].wi = Gcreatewidget(pwi, type, wattri, wattrp);
+ gfxnodes[ni].inuse = TRUE;
+ goto done;
+ }
+ wi = Gcreatewidget(pwi, type, wattri, wattrp);
+
+ done:
+ Tinsi(rootwo, wi, (cwo = Ttable(4)));
+ rtno = Tinteger(wi);
+ rtnm = Mpushmark(rtno);
+ if (pwi != -1) {
+ Tinss(cwo, "parent", Tinteger(pwi));
+ if ((pwo = Tfindi(rootwo, pwi))) {
+ if (!(cho = Tfinds(pwo, "children")))
+ Tinss(pwo, "children", (cho = Ttable(2)));
+ Tinsi(cho, wi, Tinteger(pwi));
+ }
+ }
+ Mpopmark(rtnm);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXsetwidgetattr(int argc, lvar_t * argv)
+{
+ int wi, type, rtn;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi))
+ return L_FAILURE;
+ type = Gwidgets[wi].type;
+ if ((rtn = getwattr(argv[1].o, &type)) == -1)
+ return L_FAILURE;
+ Gsetwidgetattr(wi, wattri, wattrp);
+ rtno = Tinteger(rtn);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXgetwidgetattr(int argc, lvar_t * argv)
+{
+ Tkvindex_t tkvi;
+ Tobj po, so, ro, co, co2;
+ Gwattrmap_t *mapp;
+ int *ap;
+ int li, ai, type, color, wattri2, wi;
+ long rtnm;
+
+ wattri = 0;
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) ||
+ !T_ISTABLE(argv[1].o))
+ return L_FAILURE;
+ type = Gwidgets[wi].type;
+ for (ap = NULL, li = 0; Gwlist[li].wname; li++) {
+ if (type == Gwlist[li].wid) {
+ ap = Gwlist[li].attrid;
+ break;
+ }
+ }
+ if (!ap)
+ return L_FAILURE;
+ for (Tgetfirst(argv[1].o, &tkvi); tkvi.kvp; Tgetnext(&tkvi)) {
+ if (!T_ISSTRING(tkvi.kvp->vo))
+ continue;
+ for (ai = 0; ap[ai] != -1; ai++) {
+ if (Strcmp(Gwattrmap[ap[ai]].name,
+ Tgetstring(tkvi.kvp->vo)) == 0) {
+ if (wattri >= wattrn) {
+ wattrp = Marraygrow(wattrp,
+ (long) (wattrn +
+ WATTRINCR) * WATTRSIZE);
+ wattrn += WATTRINCR;
+ }
+ if (ap[ai] == G_ATTRCOLOR) {
+ for (color = 0; color < G_MAXCOLORS; color++) {
+ if (wattri >= wattrn) {
+ wattrp = Marraygrow(wattrp,
+ (long) (wattrn +
+ WATTRINCR) *
+ WATTRSIZE);
+ wattrn += WATTRINCR;
+ }
+ wattrp[wattri].u.c.index = color;
+ wattrp[wattri++].id = ap[ai];
+ }
+ } else
+ wattrp[wattri++].id = ap[ai];
+ break;
+ }
+ }
+ }
+ if (Ggetwidgetattr(wi, wattri, wattrp) == -1)
+ return L_FAILURE;
+ rtno = Ttable(wattri);
+ rtnm = Mpushmark(rtno);
+ for (wattri2 = 0; wattri2 < wattri; wattri2++) {
+ mapp = &Gwattrmap[wattrp[wattri2].id];
+ switch (mapp->type) {
+ case G_ATTRTYPEPOINT:
+ Tinss(rtno, mapp->name, (po = Ttable(2)));
+ Tinss(po, "x", Treal(wattrp[wattri2].u.p.x));
+ Tinss(po, "y", Treal(wattrp[wattri2].u.p.y));
+ break;
+ case G_ATTRTYPESIZE:
+ Tinss(rtno, mapp->name, (so = Ttable(2)));
+ Tinss(so, "x", Treal(wattrp[wattri2].u.s.x));
+ Tinss(so, "y", Treal(wattrp[wattri2].u.s.y));
+ break;
+ case G_ATTRTYPERECT:
+ Tinss(rtno, mapp->name, (ro = Ttable(2)));
+ Tinsi(ro, 0, (po = Ttable(2)));
+ Tinss(po, "x", Treal(wattrp[wattri2].u.r.o.x));
+ Tinss(po, "y", Treal(wattrp[wattri2].u.r.o.y));
+ Tinsi(ro, 1, (po = Ttable(2)));
+ Tinss(po, "x", Treal(wattrp[wattri2].u.r.c.x));
+ Tinss(po, "y", Treal(wattrp[wattri2].u.r.c.y));
+ break;
+ case G_ATTRTYPETEXT:
+ Tinss(rtno, mapp->name, Tstring(wattrp[wattri2].u.t));
+ break;
+ case G_ATTRTYPEINT:
+ Tinss(rtno, mapp->name, Tinteger(wattrp[wattri2].u.i));
+ break;
+ case G_ATTRTYPECOLOR:
+ Tinss(rtno, mapp->name, (co = Ttable(G_MAXCOLORS)));
+ for (color = 0; color < G_MAXCOLORS; color++) {
+ Tinsi(co, color, (co2 = Ttable(3)));
+ Tinss(co2, "r", Treal(wattrp[wattri2 + color].u.c.r));
+ Tinss(co2, "g", Treal(wattrp[wattri2 + color].u.c.g));
+ Tinss(co2, "b", Treal(wattrp[wattri2 + color].u.c.g));
+ }
+ wattri2 += (G_MAXCOLORS - 1);
+ break;
+ default:
+ break;
+ }
+ }
+ Mpopmark(rtnm);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXdestroywidget(int argc, lvar_t * argv)
+{
+ Tkvindex_t tkvi;
+ Tobj wo, cho, pwio, pwo;
+ lvar_t argv2[1];
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi))
+ return L_FAILURE;
+
+ wo = Tfindi(rootwo, wi);
+ if ((cho = Tfinds(wo, "children"))) {
+ while (Tgettablen(cho) > 0) {
+ Tgetfirst(cho, &tkvi);
+ argv2[0].o = tkvi.kvp->ko;
+ GFXdestroywidget(1, argv2);
+ }
+ }
+ if ((pwio = Tfinds(wo, "parent"))) {
+ pwo = Tfindi(rootwo, Tgetinteger(pwio));
+ cho = Tfinds(pwo, "children");
+ Tdeli(cho, wi);
+ }
+ if (ISACANVAS(wi) || ISALABEL(wi)) {
+ nodeterm(NODEID(wi));
+ gfxnodes[NODEID(wi)].inuse = FALSE;
+ }
+ Gdestroywidget(wi);
+ Tdeli(rootwo, wi);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXclear(int argc, lvar_t * argv)
+{
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi))
+ return L_FAILURE;
+ Gcanvasclear(wi);
+ if (ISACANVAS(wi))
+ rectterm(NODEID(wi)), rectinit(NODEID(wi));
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXsetgfxattr(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) ||
+ getgattr(argv[1].o, &gattr) == -1)
+ return L_FAILURE;
+ Gsetgfxattr(wi, &gattr);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXgetgfxattr(int argc, lvar_t * argv)
+{
+ Tkvindex_t tkvi;
+ Ggattr_t gattr;
+ long rtnm = 0;
+ int wi;
+ char *s = 0;
+
+ gattr.flags = (Ggattrflags_t) 0;
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) ||
+ !T_ISTABLE(argv[1].o))
+ return L_FAILURE;
+ for (Tgetfirst(argv[1].o, &tkvi); tkvi.kvp; Tgetnext(&tkvi)) {
+ if (!T_ISSTRING(tkvi.kvp->vo))
+ continue;
+ s = Tgetstring(tkvi.kvp->vo);
+ if (Strcmp(s, "color") == 0)
+ gattr.flags |= G_GATTRCOLOR;
+ else if (Strcmp(s, "width") == 0)
+ gattr.flags |= G_GATTRWIDTH;
+ else if (Strcmp(s, "mode") == 0)
+ gattr.flags |= G_GATTRMODE;
+ else if (Strcmp(s, "fill") == 0)
+ gattr.flags |= G_GATTRFILL;
+ else if (Strcmp(s, "style") == 0)
+ gattr.flags |= G_GATTRSTYLE;
+ }
+ if (Ggetgfxattr(wi, &gattr) == -1)
+ return L_FAILURE;
+ rtno = Ttable(wattri);
+ rtnm = Mpushmark(rtno);
+ if (gattr.flags & G_GATTRCOLOR) {
+ Tinss(rtno, "color", Tinteger(gattr.color));
+ } else if (gattr.flags & G_GATTRWIDTH) {
+ Tinss(rtno, "width", Tinteger(gattr.width));
+ } else if (gattr.flags & G_GATTRMODE) {
+ s = (gattr.mode == G_SRC) ? "src" : "xor";
+ Tinss(rtno, "mode", Tstring(s));
+ } else if (gattr.flags & G_GATTRFILL) {
+ s = (gattr.fill) ? "on" : "off";
+ Tinss(rtno, "fill", Tstring(s));
+ } else if (gattr.flags & G_GATTRSTYLE) {
+ switch (gattr.style) {
+ case G_SOLID:
+ s = "solid";
+ break;
+ case G_DASHED:
+ s = "dashed";
+ break;
+ case G_DOTTED:
+ s = "dotted";
+ break;
+ case G_LONGDASHED:
+ s = "longdashed";
+ break;
+ case G_SHORTDASHED:
+ s = "shortdashed";
+ break;
+ }
+ Tinss(rtno, "style", Tstring(s));
+ }
+ Mpopmark(rtnm);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXarrow(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ Gpoint_t p0, p1;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getxy(argv[2].o, &p0) == -1 || getxy(argv[3].o, &p1) == -1
+ || getgattr((argc == 5) ? argv[4].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ Garrow(wi, p0, p1, &gattr);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXline(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ Gpoint_t p0, p1;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getxy(argv[2].o, &p0) == -1 || getxy(argv[3].o, &p1) == -1
+ || getgattr((argc == 5) ? argv[4].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ Gline(wi, p0, p1, &gattr);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXbox(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ Grect_t r;
+ int wi, rtn;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getrect(argv[2].o, &r) == -1
+ || getgattr((argc == 4) ? argv[3].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ rtn = Gbox(wi, r, &gattr);
+ if (rtn == 0 && argv[1].o != null && ISACANVAS(wi))
+ rectmerge(NODEID(wi), argv[1].o, r);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXpolygon(int argc, lvar_t * argv)
+{
+ Tobj po;
+ Ggattr_t gattr;
+ long i, pn;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getgattr((argc == 4) ? argv[3].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ po = argv[2].o;
+ if ((pn = Tgettablen(po)) > gpn) {
+ gpp = Marraygrow(gpp, (long) pn * GPSIZE);
+ gpn = pn;
+ }
+ for (i = 0; i < pn; i++)
+ if (getxy(Tfindi(po, i), &gpp[i]) == -1)
+ return L_FAILURE;
+ Gpolygon(wi, pn, gpp, &gattr);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXsplinegon(int argc, lvar_t * argv)
+{
+ Tobj po;
+ Ggattr_t gattr;
+ long i, pn;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getgattr((argc == 4) ? argv[3].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ po = argv[2].o;
+ if ((pn = Tgettablen(po)) > gpn) {
+ gpp = Marraygrow(gpp, (long) pn * GPSIZE);
+ gpn = pn;
+ }
+ for (i = 0; i < pn; i++)
+ if (getxy(Tfindi(po, i), &gpp[i]) == -1)
+ return L_FAILURE;
+ Gsplinegon(wi, pn, gpp, &gattr);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXarc(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ Grect_t r;
+ Gpoint_t op;
+ Gsize_t sp;
+ int wi, rtn;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getxy(argv[2].o, &op) == -1 || getxy(argv[3].o, &sp) == -1
+ || getgattr((argc == 5) ? argv[4].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ rtn = Garc(wi, op, sp, (double) 0, (double) 360, &gattr);
+ if (rtn == 0 && argv[1].o != null && ISACANVAS(wi)) {
+ r.o.x = op.x - sp.x, r.o.y = op.y - sp.y;
+ r.c.x = op.x + sp.x, r.c.y = op.y + sp.y;
+ rectmerge(NODEID(wi), argv[1].o, r);
+ }
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXtext(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ Gpoint_t p;
+ char *s, *fn, *justs;
+ double fs;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getxy(argv[2].o, &p) == -1 || getstr(argv[3].o, &s) == -1
+ || getstr(argv[4].o, &fn) == -1 || getdouble(argv[5].o, &fs) == -1
+ || getstr(argv[6].o, &justs) == -1
+ || getgattr((argc == 8) ? argv[7].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ Gtext(wi, s, p, fn, fs, justs, &gattr);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXtextsize(int argc, lvar_t * argv)
+{
+ Gsize_t sp;
+ double fs;
+ char *s, *fn;
+ long m;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS(wi) ||
+ getstr(argv[1].o, &s) == -1 || getstr(argv[2].o, &fn) == -1 ||
+ getdouble(argv[3].o, &fs) == -1)
+ return L_FAILURE;
+ if (Ggettextsize(wi, s, fn, fs, &sp) == -1)
+ return L_FAILURE;
+ m = Mpushmark((rtno = Ttable(2)));
+ Tinss(rtno, "x", Treal(sp.x)), Tinss(rtno, "y", Treal(sp.y));
+ Mpopmark(m);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXcreatebitmap(int argc, lvar_t * argv)
+{
+ Tobj bo, so;
+ Gsize_t s;
+ long rtnm;
+ int wi, bi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getxy(argv[1].o, &s) == -1)
+ return L_FAILURE;
+ if ((bi = Gcreatebitmap(wi, s)) == -1)
+ return L_FAILURE;
+ Tinsi(rootbo, bi, (bo = Ttable(4)));
+ rtno = Tinteger(bi);
+ rtnm = Mpushmark(rtno);
+ Tinss(bo, "canvas", Tinteger(bi));
+ Tinss(bo, "size", (so = Ttable(2)));
+ Tinss(so, "x", Tinteger((long) Gbitmaps[bi].size.x));
+ Tinss(so, "y", Tinteger((long) Gbitmaps[bi].size.y));
+ Mpopmark(rtnm);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXdestroybitmap(int argc, lvar_t * argv)
+{
+ int bi;
+
+ if (getint(argv[0].o, &bi) == -1 || !ISABITMAP(bi))
+ return L_FAILURE;
+ Gdestroybitmap(bi);
+ Tdeli(rootbo, bi);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXreadbitmap(int argc, lvar_t * argv)
+{
+ Tobj bo, so;
+ long rtnm;
+ int wi, bi, ioi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getint(argv[1].o, &ioi) == -1 || ioi < 0 || ioi > ion
+ || !iop[ioi].inuse)
+ return L_FAILURE;
+ if ((bi = Greadbitmap(wi, iop[ioi].ifp)) == -1)
+ return L_FAILURE;
+ Tinsi(rootbo, bi, (bo = Ttable(4)));
+ rtno = Tinteger(bi);
+ rtnm = Mpushmark(rtno);
+ Tinss(bo, "canvas", Tinteger(bi));
+ Tinss(bo, "size", (so = Ttable(2)));
+ Tinss(so, "x", Tinteger((long) Gbitmaps[bi].size.x));
+ Tinss(so, "y", Tinteger((long) Gbitmaps[bi].size.y));
+ Mpopmark(rtnm);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXwritebitmap(int argc, lvar_t * argv)
+{
+ int bi, ioi;
+
+ if (getint(argv[0].o, &ioi) == -1 || ioi < 0 || ioi > ion ||
+ !iop[ioi].inuse || getint(argv[1].o, &bi) == -1 || !ISABITMAP(bi))
+ return L_FAILURE;
+ Gwritebitmap(iop[ioi].ofp, bi);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXbitblt(int argc, lvar_t * argv)
+{
+ Ggattr_t gattr;
+ Grect_t r;
+ Gpoint_t p;
+ char *mode;
+ int wi, bi, rtn;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS2(wi)
+ || getxy(argv[2].o, &p) == -1 || getrect(argv[3].o, &r) == -1
+ || getint(argv[4].o, &bi) == -1 || getstr(argv[5].o, &mode) == -1
+ || getgattr((argc == 7) ? argv[6].o : NULL, &gattr) == -1)
+ return L_FAILURE;
+ rtn = Gbitblt(wi, p, r, bi, mode, &gattr);
+ if (rtn == 0 && argv[1].o != null && ISACANVAS(wi) &&
+ strcmp(mode, "b2c") == 0)
+ rectmerge(NODEID(wi), argv[1].o, r);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXclearpick(int argc, lvar_t * argv)
+{
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS(wi))
+ return L_FAILURE;
+ if (argv[1].o != null)
+ rectdelete(NODEID(wi), argv[1].o);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXsetpick(int argc, lvar_t * argv)
+{
+ Grect_t r;
+ int wi;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) || !ISACANVAS(wi) ||
+ getrect(argv[2].o, &r) == -1)
+ return L_FAILURE;
+ if (argv[1].o != null)
+ rectinsert(NODEID(wi), argv[1].o, r);
+ return L_SUCCESS;
+}
+
+/* LEFTY builtin */
+int GFXdisplaymenu(int argc, lvar_t * argv)
+{
+ Tobj mo, meo;
+ char buf[50];
+ char *entries[1];
+ int wi, mi, mei;
+ int rtn;
+
+ if (getint(argv[0].o, &wi) == -1 || !ISAWIDGET(wi) ||
+ !(ISACANVAS(wi) || ISALABEL(wi)))
+ return L_FAILURE;
+ mo = argv[1].o;
+ if ((mi = menufind(NODEID(wi), mo, Tgettime(mo))) != -1) {
+ if ((rtn = Gmenudisplay(wi, mi)) == -1)
+ rtno = NULL;
+ else
+ rtno = Tinteger(rtn);
+ return L_SUCCESS;
+ }
+ wattri = 0;
+ mi = Gcreatewidget(wi, G_MENUWIDGET, wattri, wattrp);
+ mei = 0;
+ while ((meo = Tfindi(mo, mei))) {
+ switch (Tgettype(meo)) {
+ case T_STRING:
+ entries[0] = Tgetstring(meo);
+ break;
+ case T_INTEGER:
+ sprintf(buf, "%d", (int) Tgetnumber(meo));
+ entries[0] = &buf[0];
+ break;
+ case T_REAL:
+ sprintf(buf, "%f", Tgetnumber(meo));
+ entries[0] = &buf[0];
+ break;
+ case T_CODE:
+ case T_TABLE:
+ case T_SIZE:
+ break;
+ }
+ Gmenuaddentries(mi, 1, &entries[0]);
+ mei++;
+ }
+ menuinsert(NODEID(wi), mo, Tgettime(mo), mi);
+ Ttime++;
+ if ((rtn = Gmenudisplay(wi, mi)) == -1)
+ rtno = NULL;
+ else
+ rtno = Tinteger(rtn);
+ return L_SUCCESS;
+}
+
+static int getwattr(Tobj ao, int *type)
+{
+ Tkvindex_t tkvi;
+ Tobj co;
+ int *ap;
+ char *ts;
+ int li, ai;
+
+ wattri = 0;
+ if (!ao && Tgettype(ao) != T_TABLE)
+ return -1;
+ if (*type == -1) {
+ if (getstr(Tfinds(ao, "type"), &ts) == -1)
+ return -1;
+ for (ap = NULL, li = 0; Gwlist[li].wname; li++) {
+ if (Strcmp(ts, Gwlist[li].wname) == 0) {
+ *type = Gwlist[li].wid;
+ ap = Gwlist[li].attrid;
+ break;
+ }
+ }
+ if (*type == -1)
+ return -1;
+ if (wattri >= wattrn) {
+ wattrp = Marraygrow(wattrp,
+ (long) (wattrn + WATTRINCR) * WATTRSIZE);
+ wattrn += WATTRINCR;
+ }
+ switch (*type) {
+ case G_TEXTWIDGET:
+ wattrp[wattri].id = G_ATTRNEWLINECB;
+ wattrp[wattri].u.func = (void *) (GFXtextcb), wattri++;
+ break;
+ case G_ARRAYWIDGET:
+ wattrp[wattri].id = G_ATTRRESIZECB;
+ wattrp[wattri].u.func = (void *) (GFXarrayresizecb), wattri++;
+ break;
+ case G_BUTTONWIDGET:
+ wattrp[wattri].id = G_ATTRBUTTONCB;
+ wattrp[wattri].u.func = (void *) (GFXbuttoncb), wattri++;
+ break;
+ case G_LABELWIDGET:
+ wattrp[wattri].id = G_ATTREVENTCB;
+ wattrp[wattri].u.func = (void *) (GFXlabelcb), wattri++;
+ break;
+ case G_CANVASWIDGET:
+ wattrp[wattri].id = G_ATTREVENTCB;
+ wattrp[wattri].u.func = (void *) (GFXevent), wattri++;
+ break;
+ case G_VIEWWIDGET:
+ wattrp[wattri].id = G_ATTREVENTCB;
+ wattrp[wattri].u.func = (void *) (GFXviewcb), wattri++;
+ break;
+ }
+ } else {
+ for (ap = NULL, li = 0; Gwlist[li].wname; li++) {
+ if (*type == Gwlist[li].wid) {
+ ap = Gwlist[li].attrid;
+ break;
+ }
+ }
+ }
+ for (ai = 0; ap[ai] != -1; ai++) {
+ if (wattri >= wattrn) {
+ wattrp = Marraygrow(wattrp,
+ (long) (wattrn + WATTRINCR) * WATTRSIZE);
+ wattrn += WATTRINCR;
+ }
+ wattrp[wattri].id = ap[ai];
+ switch (Gwattrmap[ap[ai]].type) {
+ case G_ATTRTYPEPOINT:
+ getwpointnset(Tfinds(ao, Gwattrmap[ap[ai]].name));
+ break;
+ case G_ATTRTYPESIZE:
+ getwsizenset(Tfinds(ao, Gwattrmap[ap[ai]].name));
+ break;
+ case G_ATTRTYPERECT:
+ getwrectnset(Tfinds(ao, Gwattrmap[ap[ai]].name));
+ break;
+ case G_ATTRTYPETEXT:
+ getwstrnset(Tfinds(ao, Gwattrmap[ap[ai]].name));
+ break;
+ case G_ATTRTYPEINT:
+ getwintnset(Tfinds(ao, Gwattrmap[ap[ai]].name));
+ break;
+ case G_ATTRTYPECOLOR:
+ if ((co = Tfinds(ao, Gwattrmap[ap[ai]].name)) &&
+ Tgettype(co) == T_TABLE) {
+ for (Tgetfirst(co, &tkvi); tkvi.kvp; Tgetnext(&tkvi)) {
+ if (wattri >= wattrn) {
+ wattrp =
+ Marraygrow(wattrp,
+ (long) (wattrn +
+ WATTRINCR) * WATTRSIZE);
+ wattrn += WATTRINCR;
+ }
+ wattrp[wattri].id = ap[ai];
+ getwcolornset(tkvi.kvp->ko, tkvi.kvp->vo);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return wattri;
+}
+
+static int getgattr(Tobj ao, Ggattr_t * dp)
+{
+ Tkvindex_t tkvi;
+ char *s, *s2;
+
+ dp->flags = (Ggattrflags_t) 0;
+ if (!ao)
+ return 0;
+ if (Tgettype(ao) != T_TABLE)
+ return -1;
+ for (Tgetfirst(ao, &tkvi); tkvi.kvp; Tgetnext(&tkvi)) {
+ if (Tgettype(tkvi.kvp->ko) != T_STRING)
+ continue;
+ s = Tgetstring(tkvi.kvp->ko);
+ if (Strcmp(s, "color") == 0) {
+ getaintnset(tkvi.kvp->vo, dp->color, G_GATTRCOLOR);
+ } else if (Strcmp(s, "width") == 0) {
+ getaintnset(tkvi.kvp->vo, dp->width, G_GATTRWIDTH);
+ } else if (Strcmp(s, "mode") == 0) {
+ getastrnset(tkvi.kvp->vo, s2, G_GATTRMODE);
+ if (dp->flags & G_GATTRMODE) {
+ if (Strcmp(s2, "src") == 0)
+ dp->mode = G_SRC;
+ else if (Strcmp(s2, "xor") == 0)
+ dp->mode = G_XOR;
+ else
+ dp->flags &= ~G_GATTRMODE;
+ }
+ } else if (Strcmp(s, "fill") == 0) {
+ getastrnset(tkvi.kvp->vo, s2, G_GATTRFILL);
+ if (dp->flags & G_GATTRFILL) {
+ if (Strcmp(s2, "on") == 0)
+ dp->fill = 1;
+ else if (Strcmp(s2, "off") == 0)
+ dp->fill = 0;
+ else
+ dp->flags &= ~G_GATTRFILL;
+ }
+ } else if (Strcmp(s, "style") == 0) {
+ getastrnset(tkvi.kvp->vo, s2, G_GATTRSTYLE);
+ if (dp->flags & G_GATTRSTYLE) {
+ if (Strcmp(s2, "solid") == 0)
+ dp->style = G_SOLID;
+ else if (Strcmp(s2, "dashed") == 0)
+ dp->style = G_DASHED;
+ else if (Strcmp(s2, "dotted") == 0)
+ dp->style = G_DOTTED;
+ else if (Strcmp(s2, "longdashed") == 0)
+ dp->style = G_LONGDASHED;
+ else if (Strcmp(s2, "shortdashed") == 0)
+ dp->style = G_SHORTDASHED;
+ else
+ dp->flags &= ~G_GATTRSTYLE;
+ }
+ }
+ }
+ return 0;
+}
+
+static int getrect(Tobj ro, Grect_t * rp)
+{
+ if (ro && Tgettype(ro) == T_TABLE)
+ if (getxy(Tfindi(ro, 0), &rp->o) != -1 &&
+ getxy(Tfindi(ro, 1), &rp->c) != -1)
+ return 0;
+ return -1;
+}
+
+static int getxy(Tobj po, Gxy_t * xyp)
+{
+ Tobj xo, yo;
+
+ if (po && Tgettype(po) == T_TABLE) {
+ xo = Tfinds(po, "x"), yo = Tfinds(po, "y");
+ if (xo && T_ISNUMBER(xo) && yo && T_ISNUMBER(yo)) {
+ xyp->x = Tgetnumber(xo), xyp->y = Tgetnumber(yo);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int getint(Tobj to, int *ip)
+{
+ if (to && T_ISNUMBER(to)) {
+ *ip = Tgetnumber(to);
+ return 0;
+ }
+ return -1;
+}
+
+static int getdouble(Tobj to, double *dp)
+{
+ if (to && T_ISNUMBER(to)) {
+ *dp = Tgetnumber(to);
+ return 0;
+ }
+ return -1;
+}
+
+static int getstr(Tobj so, char **s)
+{
+ if (so && T_ISSTRING(so)) {
+ *s = Tgetstring(so);
+ return 0;
+ }
+ return -1;
+}
+
+/* scan a string for 3 floating point numbers separated by
+ * white-space or commas.
+ */
+static int scanhsv(char *strp, double *h, double *s, double *v)
+{
+ char *endp;
+
+ *h = strtod(strp, &endp);
+ if (endp == strp)
+ return 0;
+ strp = endp;
+ while ((*strp == ',') || isspace(*strp))
+ strp++;
+ *s = strtod(strp, &endp);
+ if (endp == strp)
+ return 0;
+ strp = endp;
+ while ((*strp == ',') || isspace(*strp))
+ strp++;
+ *v = strtod(strp, &endp);
+ if (endp == strp)
+ return 0;
+ return 1;
+}
+
+static void hsv2rgb(double h, double s, double v, Gcolor_t * cp)
+{
+ double r, g, b;
+ double f, p, q, t;
+ int i;
+
+ /* clip to reasonable values */
+ h = max(min(h, 1.0), 0.0);
+ s = max(min(s, 1.0), 0.0);
+ v = max(min(v, 1.0), 0.0);
+
+ r = g = b = v;
+ if (s != 0.0) {
+ if (h == 1.0)
+ h = 0.0;
+ h = h * 6.0;
+ i = (int) h;
+ f = h - (double) i;
+ p = v * (1 - s);
+ q = v * (1 - (s * f));
+ t = v * (1 - (s * (1 - f)));
+ switch (i) {
+ case 0:
+ r = v;
+ g = t;
+ b = p;
+ break;
+ case 1:
+ r = q;
+ g = v;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = v;
+ b = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ b = v;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = v;
+ break;
+ case 5:
+ r = v;
+ g = p;
+ b = q;
+ break;
+ }
+ }
+ cp->r = (int) (255.0 * r);
+ cp->g = (int) (255.0 * g);
+ cp->b = (int) (255.0 * b);
+}
+
+static int getcolor(Tobj ko, Tobj co, Gcolor_t * cp)
+{
+ Tobj ro, go, bo, ho, so, vo;
+ char *s, *s1, *s2;
+ double hc, sc, vc;
+ int cni;
+
+ if (ko && T_ISNUMBER(ko))
+ cp->index = Tgetnumber(ko);
+ else
+ return -1;
+ if (!co || !(T_ISSTRING(co) || T_ISTABLE(co)))
+ return -1;
+ if (T_ISSTRING(co)) {
+ unsigned int r, g, b, a;
+
+ s = Tgetstring(co);
+ while (*s == ' ')
+ s++; /* skip over any leading spaces */
+ if ((*s == '#')
+ && (sscanf(s, "#%2x%2x%2x%2x", &r, &g, &b, &a) >= 3)) {
+ cp->r = r;
+ cp->g = g;
+ cp->b = b;
+ return 0;
+ }
+ if ((isdigit(*s) || (*s == '.')) && scanhsv(s, &hc, &sc, &vc)) {
+ hsv2rgb(hc, sc, vc, cp);
+ return 0;
+ }
+ for (cni = 0; cni < sizeof(colornames) / sizeof(colorname_t);
+ cni++) {
+ for (s1 = colornames[cni].name, s2 = s; *s1 && *s2; s1++, s2++) {
+ if (*s2 == ' ' || *s2 == '_')
+ s2++;
+ else if (*s1 != *s2)
+ break;
+ }
+ if (*s1 != *s2)
+ continue;
+ cp->r = colornames[cni].r;
+ cp->g = colornames[cni].g;
+ cp->b = colornames[cni].b;
+ return 0;
+ }
+ return -1;
+ } else {
+ ro = Tfinds(co, "r");
+ go = Tfinds(co, "g");
+ bo = Tfinds(co, "b");
+ if (ro && T_ISNUMBER(ro) && go && T_ISNUMBER(go) &&
+ bo && T_ISNUMBER(bo)) {
+ cp->r = Tgetnumber(ro);
+ cp->g = Tgetnumber(go);
+ cp->b = Tgetnumber(bo);
+ return 0;
+ } else {
+ ho = Tfinds(co, "h");
+ so = Tfinds(co, "s");
+ vo = Tfinds(co, "v");
+ if (ho && T_ISNUMBER(ho) && so && T_ISNUMBER(so) &&
+ vo && T_ISNUMBER(vo)) {
+ hc = Tgetnumber(ho);
+ sc = Tgetnumber(so);
+ vc = Tgetnumber(vo);
+ hsv2rgb(hc, sc, vc, cp);
+ return 0;
+ } else
+ return -1;
+ }
+ }
+ /* return -1; */
+}
+
+static void nodeinit(int ni)
+{
+ int li, ki;
+
+ for (li = 0; li < LISTSIZE; li++)
+ gfxnodes[ni].rect[li] = NULL, gfxnodes[ni].menu[li] = NULL;
+ gfxnodes[ni].ls = gfxnodes[ni].ms = gfxnodes[ni].rs = 0;
+ for (ki = 0; ki < 256; ki++)
+ gfxnodes[ni].ks[ki] = 0;
+ gfxnodes[ni].plvo = gfxnodes[ni].pmvo = gfxnodes[ni].prvo = 0;
+ for (ki = 0; ki < 256; ki++)
+ gfxnodes[ni].pkvo[ki] = 0;
+}
+
+static void nodeterm(int ni)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp, *nrp;
+ gfxmenu_t **mp;
+ gfxmenu_t *cmp, *nmp;
+ int li;
+
+ for (li = 0; li < LISTSIZE; li++) {
+ rp = &gfxnodes[ni].rect[li];
+ for (crp = *rp; crp; crp = nrp)
+ nrp = crp->next, free(crp);
+ *rp = NULL;
+ mp = &gfxnodes[ni].menu[li];
+ for (cmp = *mp; cmp; cmp = nmp)
+ nmp = cmp->next, free(cmp);
+ *mp = NULL;
+ }
+}
+
+static void rectinit(int ni)
+{
+ int li;
+
+ for (li = 0; li < LISTSIZE; li++)
+ gfxnodes[ni].rect[li] = NULL;
+}
+
+static void rectterm(int ni)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp, *nrp;
+ int li;
+
+ for (li = 0; li < LISTSIZE; li++) {
+ rp = &gfxnodes[ni].rect[li];
+ for (crp = *rp; crp; crp = nrp)
+ nrp = crp->next, free(crp);
+ *rp = NULL;
+ }
+}
+
+static void rectinsert(int ni, Tobj ko, Grect_t r)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp;
+
+ rp = &gfxnodes[ni].rect[(unsigned long) ko % LISTSIZE];
+ for (crp = *rp; crp; crp = crp->next)
+ if (crp->ko == ko) {
+ crp->r.o.x = min(r.o.x, r.c.x);
+ crp->r.o.y = min(r.o.y, r.c.y);
+ crp->r.c.x = max(r.o.x, r.c.x);
+ crp->r.c.y = max(r.o.y, r.c.y);
+ return;
+ }
+ if (!(crp = malloc(sizeof(gfxrect_t))))
+ panic(POS, "rectinsert", "rect malloc failed");
+
+ crp->ko = ko;
+ crp->r.o.x = min(r.o.x, r.c.x);
+ crp->r.o.y = min(r.o.y, r.c.y);
+ crp->r.c.x = max(r.o.x, r.c.x);
+ crp->r.c.y = max(r.o.y, r.c.y);
+ crp->next = *rp;
+ *rp = crp;
+}
+
+static void rectmerge(int ni, Tobj ko, Grect_t r)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp;
+
+ rp = &gfxnodes[ni].rect[(unsigned long) ko % LISTSIZE];
+ for (crp = *rp; crp; crp = crp->next)
+ if (crp->ko == ko) {
+ crp->r.o.x = min(crp->r.o.x, min(r.o.x, r.c.x));
+ crp->r.o.y = min(crp->r.o.y, min(r.o.y, r.c.y));
+ crp->r.c.x = max(crp->r.c.x, max(r.o.x, r.c.x));
+ crp->r.c.y = max(crp->r.c.y, max(r.o.y, r.c.y));
+ return;
+ }
+ if (!(crp = malloc(sizeof(gfxrect_t))))
+ panic(POS, "rectmerge", "rect malloc failed");
+
+ crp->ko = ko;
+ crp->r.o.x = min(r.o.x, r.c.x);
+ crp->r.o.y = min(r.o.y, r.c.y);
+ crp->r.c.x = max(r.o.x, r.c.x);
+ crp->r.c.y = max(r.o.y, r.c.y);
+ crp->next = *rp;
+ *rp = crp;
+}
+
+static Tobj rectfind(int ni, Gpoint_t p)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp;
+ int li;
+
+ for (li = 0; li < LISTSIZE; li++) {
+ rp = &gfxnodes[ni].rect[li];
+ for (crp = *rp; crp; crp = crp->next)
+ if (crp->r.o.x <= p.x && crp->r.c.x >= p.x &&
+ crp->r.o.y <= p.y && crp->r.c.y >= p.y)
+ return crp->ko;
+ }
+ return NULL;
+}
+
+static void rectdelete(int ni, Tobj ko)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp, *prp;
+
+ rp = &gfxnodes[ni].rect[(unsigned long) ko % LISTSIZE];
+ for (crp = *rp, prp = NULL; crp; prp = crp, crp = crp->next)
+ if (crp->ko == ko) {
+ if (crp == *rp)
+ *rp = crp->next;
+ else
+ prp->next = crp->next;
+ free(crp);
+ return;
+ }
+}
+
+static void rectprune(int ni)
+{
+ gfxrect_t **rp;
+ gfxrect_t *crp, *prp;
+ int li;
+
+ for (li = 0; li < LISTSIZE; li++) {
+ rp = &gfxnodes[ni].rect[li];
+ for (crp = *rp, prp = NULL; crp;) {
+ if (!M_AREAOF(crp->ko)) {
+ if (crp == *rp)
+ *rp = crp->next, free(crp), crp = *rp;
+ else
+ prp->next = crp->next, free(crp), crp = prp->next;
+ } else
+ prp = crp, crp = crp->next;
+ }
+ }
+}
+
+static void menuinsert(int ni, Tobj ko, long time, int mi)
+{
+ gfxmenu_t **mp;
+ gfxmenu_t *cmp;
+
+ mp = &gfxnodes[ni].menu[(unsigned long) ko % LISTSIZE];
+ for (cmp = *mp; cmp; cmp = cmp->next)
+ if (cmp->ko == ko) {
+ cmp->time = time, cmp->mi = mi;
+ return;
+ }
+ if (!(cmp = malloc(sizeof(gfxmenu_t))))
+ panic(POS, "menuinsert", "menu malloc failed");
+
+ cmp->ko = ko;
+ cmp->time = time;
+ cmp->mi = mi;
+ cmp->next = *mp;
+ *mp = cmp;
+}
+
+static int menufind(int ni, Tobj ko, long time)
+{
+ gfxmenu_t **mp;
+ gfxmenu_t *cmp;
+
+ mp = &gfxnodes[ni].menu[(unsigned long) ko % LISTSIZE];
+ for (cmp = *mp; cmp; cmp = cmp->next)
+ if (cmp->ko == ko && cmp->time == time)
+ return cmp->mi;
+ return -1;
+}
+
+static void menuprune(int ni)
+{
+ gfxmenu_t **mp;
+ gfxmenu_t *cmp, *pmp;
+ int li;
+
+ for (li = 0; li < LISTSIZE; li++) {
+ mp = &gfxnodes[ni].menu[li];
+ for (cmp = *mp, pmp = NULL; cmp;) {
+ if (!M_AREAOF(cmp->ko)) {
+ if (cmp == *mp)
+ *mp = cmp->next, free(cmp), cmp = *mp;
+ else
+ pmp->next = cmp->next, free(cmp), cmp = pmp->next;
+ } else
+ pmp = cmp, cmp = cmp->next;
+ }
+ }
+}
--- /dev/null
+/* $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 _GFXVIEW_H
+#define _GFXVIEW_H
+ void GFXinit(void);
+ void GFXterm(void);
+ void GFXprune(void);
+ void GFXlabelcb(Gevent_t *);
+ void GFXviewcb(Gevent_t *);
+ void GFXevent(Gevent_t *);
+ void GFXmove(void);
+ void GFXredraw(void);
+ void GFXtextcb(int, char *);
+ void GFXbuttoncb(int, void *);
+ void GFXmonitorfile(int);
+ void GFXidle(void);
+
+ int GFXcreatewidget(int, lvar_t *);
+ int GFXsetwidgetattr(int, lvar_t *);
+ int GFXgetwidgetattr(int, lvar_t *);
+ int GFXdestroywidget(int, lvar_t *);
+ int GFXclear(int, lvar_t *);
+ int GFXsetgfxattr(int, lvar_t *);
+ int GFXgetgfxattr(int, lvar_t *);
+ int GFXarrow(int, lvar_t *);
+ int GFXline(int, lvar_t *);
+ int GFXbox(int, lvar_t *);
+ int GFXpolygon(int, lvar_t *);
+ int GFXsplinegon(int, lvar_t *);
+ int GFXarc(int, lvar_t *);
+ int GFXtext(int, lvar_t *);
+ int GFXtextsize(int, lvar_t *);
+ int GFXcreatebitmap(int, lvar_t *);
+ int GFXdestroybitmap(int, lvar_t *);
+ int GFXreadbitmap(int, lvar_t *);
+ int GFXwritebitmap(int, lvar_t *);
+ int GFXbitblt(int, lvar_t *);
+ int GFXclearpick(int, lvar_t *);
+ int GFXsetpick(int, lvar_t *);
+ int GFXdisplaymenu(int, lvar_t *);
+#endif /* _GFXVIEW_H */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* $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 "g.h"
+#include "mem.h"
+#include "io.h"
+#include "code.h"
+#include "tbl.h"
+#include "parse.h"
+#include "exec.h"
+#include "display.h"
+#include "txtview.h"
+#include "gfxview.h"
+#ifdef FEATURE_DOT
+#include "dot2l.h"
+#endif
+#ifdef FEATURE_GMAP
+#include "gmap2l.h"
+#endif
+#include "internal.h"
+#ifndef FEATURE_MS
+#include <sys/time.h>
+#ifdef HAVE_UNISTD_H
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#endif
+
+int Idump(int, Tonm_t *);
+int Icopy(int, Tonm_t *);
+int Iremove(int, Tonm_t *);
+int Itablesize(int, Tonm_t *);
+int Iopenio(int, Tonm_t *);
+int Icloseio(int, Tonm_t *);
+int Ireadline(int, Tonm_t *);
+int Iread(int, Tonm_t *);
+int Iwriteline(int, Tonm_t *);
+int Iatan(int, Tonm_t *);
+int Itan(int, Tonm_t *);
+int Icos(int, Tonm_t *);
+int Isin(int, Tonm_t *);
+int Isqrt(int, Tonm_t *);
+int Irandom(int, Tonm_t *);
+int Intos(int, Tonm_t *);
+int Iston(int, Tonm_t *);
+int Isplit(int, Tonm_t *);
+int Iconcat(int, Tonm_t *);
+int Iquote(int, Tonm_t *);
+int Itoint(int, Tonm_t *);
+int Istrlen(int, Tonm_t *);
+int Iload(int, Tonm_t *);
+int Irun(int, Tonm_t *);
+int Imonitor(int, Tonm_t *);
+int Iidlerun(int, Tonm_t *);
+int Itime(int, Tonm_t *);
+int Isleep(int, Tonm_t *);
+int Iecho(int, Tonm_t *);
+int Igetenv(int, Tonm_t *);
+int Iputenv(int, Tonm_t *);
+int Isystem(int, Tonm_t *);
+int Iexit(int, Tonm_t *);
+#ifdef FEATURE_DOT
+int Iparsegraphlabel(int, Tonm_t *);
+int Ireadgraph(int, Tonm_t *);
+int Iwritegraph(int, Tonm_t *);
+#endif
+#ifdef FEATURE_CS
+int C2Lreadcsmessage(int, Tonm_t *);
+#endif
+
+#define MAXN 10000
+
+Ifunc_t Ifuncs[] = {
+ {"createwidget", GFXcreatewidget, 2, 2},
+ {"setwidgetattr", GFXsetwidgetattr, 2, 2},
+ {"getwidgetattr", GFXgetwidgetattr, 2, 2},
+ {"destroywidget", GFXdestroywidget, 1, 1},
+ {"clear", GFXclear, 1, 1},
+ {"setgfxattr", GFXsetgfxattr, 2, 2},
+ {"getgfxattr", GFXgetgfxattr, 2, 2},
+ {"arrow", GFXarrow, 4, 5},
+ {"line", GFXline, 4, 5},
+ {"box", GFXbox, 3, 4},
+ {"polygon", GFXpolygon, 3, 4},
+ {"splinegon", GFXsplinegon, 3, 4},
+ {"arc", GFXarc, 4, 5},
+ {"text", GFXtext, 7, 8},
+ {"textsize", GFXtextsize, 4, 4},
+ {"createbitmap", GFXcreatebitmap, 2, 2},
+ {"destroybitmap", GFXdestroybitmap, 1, 1},
+ {"readbitmap", GFXreadbitmap, 2, 2},
+ {"writebitmap", GFXwritebitmap, 2, 2},
+ {"bitblt", GFXbitblt, 6, 7},
+ {"clearpick", GFXclearpick, 2, 2},
+ {"setpick", GFXsetpick, 3, 3},
+ {"displaymenu", GFXdisplaymenu, 2, 2},
+ {"txtview", TXTmode, 1, 1},
+ {"ask", TXTask, 1, 3},
+ {"dump", Idump, 0, MAXN},
+ {"copy", Icopy, 1, 1},
+ {"remove", Iremove, 1, 2},
+ {"tablesize", Itablesize, 1, 1},
+ {"openio", Iopenio, 3, 4},
+ {"closeio", Icloseio, 1, 2},
+ {"readline", Ireadline, 1, 1},
+ {"read", Iread, 1, 1},
+ {"writeline", Iwriteline, 2, 2},
+ {"atan", Iatan, 2, 2},
+ {"tan", Itan, 1, 1},
+ {"cos", Icos, 1, 1},
+ {"sin", Isin, 1, 1},
+ {"sqrt", Isqrt, 1, 1},
+ {"random", Irandom, 1, 1},
+ {"ntos", Intos, 1, 1},
+ {"ston", Iston, 1, 1},
+ {"split", Isplit, 2, 2},
+ {"concat", Iconcat, 1, MAXN},
+ {"quote", Iquote, 1, 3},
+ {"toint", Itoint, 1, 1},
+ {"strlen", Istrlen, 1, 1},
+ {"load", Iload, 1, 1},
+ {"run", Irun, 1, 1},
+ {"monitor", Imonitor, 2, 2},
+ {"idlerun", Iidlerun, 1, 1},
+ {"time", Itime, 0, 0},
+ {"sleep", Isleep, 1, 1},
+ {"echo", Iecho, 1, MAXN},
+ {"getenv", Igetenv, 1, 1},
+ {"putenv", Iputenv, 2, 2},
+ {"system", Isystem, 1, MAXN},
+ {"exit", Iexit, 0, 0},
+#ifdef FEATURE_DOT
+ {"parsegraphlabel", Iparsegraphlabel, 2, 2},
+ {"readgraph", Ireadgraph, 1, 2},
+ {"writegraph", Iwritegraph, 3, 3},
+#endif
+#ifdef FEATURE_CS
+ {"readcsmessage", C2Lreadcsmessage, 1, 1},
+#endif
+#ifdef FEATURE_GMAP
+ {"createwindow", G2Lcreatewindow, 2, 2},
+ {"destroywindow", G2Ldestroywindow, 1, 1},
+ {"setwindowattr", G2Lsetwindowattr, 2, 2},
+ {"getwindowattr", G2Lgetwindowattr, 2, 2},
+ {"createchannel", G2Lcreatechannel, 2, 2},
+ {"destroychannel", G2Ldestroychannel, 1, 1},
+ {"setchannelattr", G2Lsetchannelattr, 2, 2},
+ {"getchannelattr", G2Lgetchannelattr, 2, 2},
+ {"getchannelcoord", G2Lgetchannelcoord, 2, 2},
+ {"loadgeometry", G2Lloadgeometry, 1, 1},
+ {"unloadgeometry", G2Lunloadgeometry, 1, 1},
+ {"setgeometryattr", G2Lsetgeometryattr, 2, 2},
+ {"getgeometryattr", G2Lgetgeometryattr, 2, 2},
+ {"getgeometryitems", G2Lgetgeometryitems, 3, 3},
+ {"insertgeom2chan", G2Linsertgeom2chan, 2, 2},
+ {"removegeom2chan", G2Lremovegeom2chan, 1, 1},
+ {"loadvalue", G2Lloadvalue, 1, 1},
+ {"unloadvalue", G2Lunloadvalue, 1, 1},
+ {"setvalueattr", G2Lsetvalueattr, 2, 2},
+ {"getvalueattr", G2Lgetvalueattr, 2, 2},
+ {"getvalueitems", G2Lgetvalueitems, 2, 2},
+ {"insertval2geom", G2Linsertval2geom, 3, 3},
+ {"removeval2geom", G2Lremoveval2geom, 1, 1},
+ {"setval2geomattr", G2Lsetval2geomattr, 2, 2},
+ {"getval2geomattr", G2Lgetval2geomattr, 2, 2},
+ {"updatewindows", G2Lupdatewindows, 0, 0},
+#endif
+ {0, 0, 0, 0}
+};
+int Ifuncn;
+
+static char *bufp;
+static int bufn;
+#define BUFINCR 10240
+#define BUFSIZE sizeof (char)
+static void growbufp(int);
+
+void Iinit(void)
+{
+ int i;
+
+ if (!(bufp = malloc(BUFINCR * BUFSIZE)))
+ panic(POS, "Iinit", "buf malloc failed");
+ bufn = BUFINCR;
+ for (i = 0; Ifuncs[i].name; i++)
+ Efunction(Pfunction(Ifuncs[i].name, i), Ifuncs[i].name);
+ Ifuncn = sizeof(Ifuncs) / sizeof(Ifunc_t) - 1;
+}
+
+void Iterm(void)
+{
+ int i;
+
+ for (i = 0; i < Ifuncn; i++)
+ Tdels(root, Ifuncs[i].name);
+ Ifuncn = 0;
+ free(bufp), bufp = NULL, bufn = 0;
+}
+
+int Igetfunc(char *name)
+{
+ int i = 0;
+
+ while (Ifuncs[i].name && Strcmp(Ifuncs[i].name, name) != 0)
+ i++;
+ return (Ifuncs[i].name) ? i : -1;
+}
+
+/* display.c functions */
+
+int Idump(int argc, lvar_t * argv)
+{
+ int i;
+
+ if (argc == 0)
+ Dtrace(root, 0);
+ else
+ for (i = 0; i < argc; i++)
+ Dtrace(argv[i].o, 0);
+ return L_SUCCESS;
+}
+
+/* tbl.c functions */
+
+int Icopy(int argc, lvar_t * argv)
+{
+ rtno = Tcopy(argv[0].o);
+ return L_SUCCESS;
+}
+
+int Iremove(int argc, lvar_t * argv)
+{
+ Tobj tblo, keyo;
+
+ if (argc == 2)
+ tblo = argv[1].o, keyo = argv[0].o;
+ else
+ tblo = root, keyo = argv[0].o;
+ if (T_ISTABLE(tblo) && (T_ISNUMBER(keyo) || T_ISSTRING(keyo)))
+ Tdelo(tblo, keyo);
+ return L_SUCCESS;
+}
+
+int Itablesize(int argc, lvar_t * argv)
+{
+ Tobj vo;
+
+ if (Tgettype((vo = argv[0].o)) != T_TABLE)
+ return L_FAILURE;
+ rtno = Tinteger(((Ttable_t *) vo)->n);
+ return L_SUCCESS;
+}
+
+/* file.c functions */
+
+int Iopenio(int argc, lvar_t * argv)
+{
+ int rtn;
+
+ if (argc == 3)
+ rtn = IOopen(Tgetstring(argv[0].o),
+ Tgetstring(argv[1].o), Tgetstring(argv[2].o), NULL);
+ else
+ rtn = IOopen(Tgetstring(argv[0].o),
+ Tgetstring(argv[1].o), Tgetstring(argv[2].o),
+ Tgetstring(argv[3].o));
+ rtno = NULL;
+ if (rtn == -1)
+ return L_SUCCESS;
+ rtno = Tinteger(rtn);
+ return L_SUCCESS;
+}
+
+int Icloseio(int argc, lvar_t * argv)
+{
+ if (argc == 1)
+ IOclose((int) Tgetnumber(argv[0].o), NULL);
+ else
+ IOclose((int) Tgetnumber(argv[0].o), Tgetstring(argv[1].o));
+ return L_SUCCESS;
+}
+
+int Ireadline(int argc, lvar_t * argv)
+{
+ char *s;
+ int m, n;
+
+ s = bufp, n = bufn;
+ while ((m = IOreadline((int) Tgetnumber(argv[0].o), s, n)) != -1) {
+ if (m < n - 1)
+ break;
+ m += (s - bufp);
+ growbufp(bufn + BUFINCR);
+ s = bufp + m, n = bufn - m;
+ }
+ if (m != -1)
+ rtno = Tstring(bufp);
+ else
+ rtno = NULL;
+ return L_SUCCESS;
+}
+
+int Iread(int argc, lvar_t * argv)
+{
+ if (IOread((int) Tgetnumber(argv[0].o), bufp, bufn) > 0)
+ rtno = Tstring(bufp);
+ else
+ rtno = NULL;
+ return L_SUCCESS;
+}
+
+int Iwriteline(int argc, lvar_t * argv)
+{
+ IOwriteline((int) Tgetnumber(argv[0].o), Tgetstring(argv[1].o));
+ return L_SUCCESS;
+}
+
+/* math functions */
+
+int Iatan(int argc, lvar_t * argv)
+{
+ double x, y;
+
+ y = Tgetnumber(argv[0].o), x = Tgetnumber(argv[1].o);
+ rtno = Treal(180 * atan2(y, x) / M_PI);
+ return L_SUCCESS;
+}
+
+int Itan(int argc, lvar_t * argv)
+{
+ rtno = Treal(tan(M_PI * Tgetnumber(argv[0].o) / 180.0));
+ return L_SUCCESS;
+}
+
+int Icos(int argc, lvar_t * argv)
+{
+ rtno = Treal(cos(M_PI * Tgetnumber(argv[0].o) / 180.0));
+ return L_SUCCESS;
+}
+
+int Isin(int argc, lvar_t * argv)
+{
+ rtno = Treal(sin(M_PI * Tgetnumber(argv[0].o) / 180.0));
+ return L_SUCCESS;
+}
+
+int Isqrt(int argc, lvar_t * argv)
+{
+ rtno = Treal(sqrt(Tgetnumber(argv[0].o)));
+ return L_SUCCESS;
+}
+
+/* the gnu way is to test for a feature explicitly */
+#ifndef HAVE_LRAND48
+#define lrand48 rand
+#endif
+/* the othe way is to presume a feature based on the OS */
+#if defined(FEATURE_MS) || defined(__Mac_OSX__)
+#define lrand48 rand
+#endif
+
+int Irandom(int argc, lvar_t * argv)
+{
+ rtno = Treal((Tgetnumber(argv[0].o) *
+ (lrand48() & 0xffff)) / (double) (0xffff));
+ return L_SUCCESS;
+}
+
+/* conversion functions */
+
+int Intos(int argc, lvar_t * argv)
+{
+ double d;
+
+ d = Tgetnumber(argv[0].o);
+ if ((long) d == d)
+ sprintf(bufp, "%ld", (long) d);
+ else
+ sprintf(bufp, "%f", d);
+ rtno = Tstring(bufp);
+ return L_SUCCESS;
+}
+
+int Iston(int argc, lvar_t * argv)
+{
+ rtno = Treal((double) atof(Tgetstring(argv[0].o)));
+ return L_SUCCESS;
+}
+
+int Isplit(int argc, lvar_t * argv)
+{
+ Tobj so, fo;
+ char *sp, *sp2, *s;
+ char fc, tc, qmode;
+ long rtnm, rtni;
+ int bufi;
+
+ if (Tgettype((so = argv[0].o)) != T_STRING ||
+ Tgettype((fo = argv[1].o)) != T_STRING)
+ return L_FAILURE;
+ sp = Tgetstring(so);
+ s = Tgetstring(fo);
+ if (s[0] == '\\' && s[1] == 'n')
+ fc = '\n';
+ else
+ fc = s[0];
+ rtno = Ttable(4);
+ rtnm = Mpushmark(rtno);
+ rtni = 0;
+ if (s[0] == 0) {
+ for (sp2 = sp; *sp2; sp2++) {
+ tc = *(sp2 + 1), *(sp2 + 1) = '\000';
+ Tinsi(rtno, rtni++, Tstring(sp2));
+ *(sp2 + 1) = tc;
+ }
+ } else if (fc == ' ' || fc == ' ') {
+ while (*sp == fc)
+ sp++;
+ while (*sp) {
+ bufi = 0;
+ qmode = 0;
+ for (sp2 = sp; *sp2; sp2++) {
+ if (bufi == bufn)
+ growbufp(bufn + BUFINCR);
+ if (*sp2 == '"' || *sp2 == '\'') {
+ if (qmode) {
+ if (qmode == *sp2)
+ qmode = 0;
+ else
+ bufp[bufi++] = *sp2;
+ } else
+ qmode = *sp2;
+ } else if (*sp2 == fc && !qmode)
+ break;
+ else
+ bufp[bufi++] = *sp2;
+ }
+ if (bufi == bufn)
+ growbufp(bufn + BUFINCR);
+ bufp[bufi] = 0;
+ Tinsi(rtno, rtni++, Tstring(bufp));
+ while (*sp2 == fc)
+ sp2++;
+ sp = sp2;
+ }
+ } else {
+ while (*sp) {
+ for (sp2 = sp; *sp2 && *sp2 != fc; sp2++);
+ tc = *sp2, *sp2 = '\000';
+ Tinsi(rtno, rtni++, Tstring(sp));
+ *sp2 = tc;
+ if (*sp2) {
+ sp2++;
+ if (!*sp2)
+ Tinsi(rtno, rtni++, Tstring(""));
+ }
+ sp = sp2;
+ }
+ }
+ Mpopmark(rtnm);
+ return L_SUCCESS;
+}
+
+int Iconcat(int argc, lvar_t * argv)
+{
+ Tobj ao;
+ char buf2[50];
+ char *s;
+ int i, n, bufi;
+
+ for (bufi = 0, i = 0; i < argc; i++) {
+ ao = argv[i].o;
+ switch (Tgettype(argv[i].o)) {
+ case T_STRING:
+ if (bufi + (n = strlen(Tgetstring(ao)) + 1) > bufn)
+ growbufp(bufi + n);
+ for (s = Tgetstring(ao); *s; s++)
+ bufp[bufi++] = *s;
+ break;
+ case T_INTEGER:
+ if (bufi + 50 > bufn)
+ growbufp(bufi + 50);
+ sprintf(buf2, "%ld", Tgetinteger(ao));
+ for (s = buf2; *s; s++)
+ bufp[bufi++] = *s;
+ break;
+ case T_REAL:
+ if (bufi + 50 > bufn)
+ growbufp(bufi + 50);
+ sprintf(buf2, "%f", Tgetreal(ao));
+ for (s = buf2; *s; s++)
+ bufp[bufi++] = *s;
+ break;
+ case T_CODE:
+ case T_TABLE:
+ case T_SIZE:
+ break;
+ }
+ }
+ bufp[bufi] = '\000';
+ rtno = Tstring(bufp);
+ return L_SUCCESS;
+}
+
+int Iquote(int argc, lvar_t * argv)
+{
+ Tobj so, ao = NULL, qo = NULL;
+ char *s, *s1, *s2, *qs, *as;
+ char buf2[50];
+ int n, bufi;
+ s = 0;
+
+ if ((Tgettype((so = argv[0].o)) != T_STRING && !T_ISNUMBER(so)) ||
+ (argc > 1 && Tgettype((qo = argv[1].o)) != T_STRING) ||
+ (argc > 2 && Tgettype((ao = argv[2].o)) != T_STRING))
+ return L_FAILURE;
+ switch (Tgettype(so)) {
+ case T_STRING:
+ s = Tgetstring(so);
+ break;
+ case T_INTEGER:
+ sprintf(buf2, "%ld", Tgetinteger(so));
+ s = &buf2[0];
+ break;
+ case T_REAL:
+ sprintf(buf2, "%f", Tgetreal(so));
+ s = &buf2[0];
+ break;
+ case T_CODE:
+ case T_TABLE:
+ case T_SIZE:
+ break;
+ }
+ if (argc > 1)
+ qs = Tgetstring(qo);
+ else
+ qs = "'\"";
+ if (argc > 2)
+ as = Tgetstring(ao);
+ else
+ as = NULL;
+ bufi = 0;
+ if ((n = strlen(s) + 3) * 2 > bufn)
+ growbufp(n * 2); /* the *2 is max for chars to quote */
+ if (as)
+ bufp[bufi++] = *as;
+ for (s1 = s; *s1; s1++) {
+ for (s2 = qs; *s2; s2++)
+ if (*s1 == *s2) {
+ bufp[bufi++] = '\\', bufp[bufi++] = *s1;
+ break;
+ }
+ if (!*s2) {
+ switch (*s1) {
+ case '\n':
+ bufp[bufi++] = '\\', bufp[bufi++] = 'n';
+ break;
+ case '\r':
+ bufp[bufi++] = '\\', bufp[bufi++] = 'r';
+ break;
+ default:
+ bufp[bufi++] = *s1;
+ break;
+ }
+ }
+ }
+ if (as)
+ bufp[bufi++] = *as;
+ bufp[bufi] = '\000';
+ rtno = Tstring(bufp);
+ return L_SUCCESS;
+}
+
+int Itoint(int argc, lvar_t * argv)
+{
+ rtno = Tinteger((long) Tgetnumber(argv[0].o));
+ return L_SUCCESS;
+}
+
+int Istrlen(int argc, lvar_t * argv)
+{
+ rtno = Tinteger(strlen(Tgetstring(argv[0].o)));
+ return L_SUCCESS;
+}
+
+/* script loading functions */
+
+int Iload(int argc, lvar_t * argv)
+{
+ Psrc_t src;
+ char *fn;
+ FILE *fp;
+ Tobj co;
+
+ if ((fn = Tgetstring(argv[0].o))) {
+ if (fn[0] == '-' && fn[1] == '\000')
+ fp = stdin;
+ else {
+ fp = NULL;
+ if ((fn = buildpath(fn, FALSE)))
+ fp = fopen(fn, "r");
+ }
+ if (fp) {
+ src.flag = FILESRC, src.s = NULL, src.fp = fp;
+ src.tok = -1, src.lnum = 1;
+ while ((co = Punit(&src)))
+ Eoktorun = TRUE, Eunit(co);
+ if (fp != stdin)
+ fclose(fp);
+ } else
+ return L_FAILURE;
+ }
+ return L_SUCCESS;
+}
+
+int Irun(int argc, lvar_t * argv)
+{
+ Psrc_t src;
+ char *s;
+ Tobj co;
+
+ if ((s = Tgetstring(argv[0].o))) {
+ src.flag = CHARSRC, src.s = s, src.fp = NULL;
+ src.tok = -1, src.lnum = 1;
+ while ((co = Punit(&src)))
+ Eoktorun = TRUE, Eunit(co);
+ }
+ return L_SUCCESS;
+}
+
+/* mode setting functions */
+
+int Imonitor(int argc, lvar_t * argv)
+{
+ Tobj mo, io;
+ char *ms;
+ int ioi;
+
+ if (Tgettype((mo = argv[0].o)) != T_STRING ||
+ (Tgettype((io = argv[1].o)) != T_INTEGER &&
+ Tgettype(io) != T_REAL))
+ return L_FAILURE;
+ ms = Tgetstring(mo), ioi = Tgetnumber(io);
+ if (ioi < 0 || ioi >= ion)
+ return L_FAILURE;
+ if (Strcmp(ms, "on") == 0)
+ IOmonitor(ioi, inputfds);
+ else if (Strcmp(ms, "off") == 0)
+ IOunmonitor(ioi, inputfds);
+ else
+ return L_FAILURE;
+ return L_SUCCESS;
+}
+
+int Iidlerun(int argc, lvar_t * argv)
+{
+ Tobj mo;
+ char *ms;
+ int mode;
+
+ if (Tgettype((mo = argv[0].o)) != T_STRING)
+ return L_SUCCESS;
+ ms = Tgetstring(mo);
+ if (Strcmp(ms, "on") == 0)
+ mode = 1;
+ else if (Strcmp(ms, "off") == 0)
+ mode = 0;
+ else
+ return L_FAILURE;
+ idlerunmode = mode;
+ return L_SUCCESS;
+}
+
+/* system functions */
+
+int Itime(int argc, lvar_t * argv)
+{
+#ifndef FEATURE_MS
+ struct timeval tz;
+
+ gettimeofday(&tz, NULL);
+ rtno = Treal(tz.tv_sec + tz.tv_usec / 1000000.0);
+#else
+ rtno = Treal(0);
+#endif
+ return L_SUCCESS;
+}
+
+int Isleep(int argc, lvar_t * argv)
+{
+#ifndef FEATURE_MS
+ struct timeval tz;
+ long l;
+
+ Gsync();
+ l = Tgetnumber(argv[0].o);
+ tz.tv_sec = l;
+ tz.tv_usec = (l - tz.tv_sec) * 1000000;
+ if (select(0, NULL, NULL, NULL, &tz) == -1)
+ return L_FAILURE;
+#endif
+ return L_SUCCESS;
+}
+
+int Iecho(int argc, lvar_t * argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ switch (Tgettype(argv[i].o)) {
+ case T_STRING:
+ printf("%s", Tgetstring(argv[i].o));
+ break;
+ case T_INTEGER:
+ printf("%ld", Tgetinteger(argv[i].o));
+ break;
+ case T_REAL:
+ printf("%f", Tgetreal(argv[i].o));
+ break;
+ case T_TABLE:
+ printf("[\n"), Dtrace(argv[i].o, 4);
+ break;
+ case T_CODE:
+ case T_SIZE:
+ break;
+ }
+ }
+ printf("\n");
+ return L_SUCCESS;
+}
+
+int Igetenv(int argc, lvar_t * argv)
+{
+ char *s;
+
+ if (!T_ISSTRING(argv[0].o))
+ return L_FAILURE;
+ if (!(s = getenv(Tgetstring(argv[0].o))) || !*s)
+ return L_SUCCESS;
+ rtno = Tstring(s);
+ return L_SUCCESS;
+}
+
+int Iputenv(int argc, lvar_t * argv)
+{
+ if (!T_ISSTRING(argv[0].o) || !T_ISSTRING(argv[1].o))
+ return L_FAILURE;
+ bufp[0] = 0;
+ strcat(bufp, Tgetstring(argv[0].o));
+ strcat(bufp, "=");
+ strcat(bufp, Tgetstring(argv[1].o));
+ putenv(bufp);
+ return L_SUCCESS;
+}
+
+int Isystem(int argc, lvar_t * argv)
+{
+ int i;
+
+ bufp[0] = 0;
+ strcat(bufp, Tgetstring(argv[0].o));
+ for (i = 1; i < argc; i++)
+ strcat(bufp, " "), strcat(bufp, Tgetstring(argv[i].o));
+#ifndef FEATURE_MS
+ system(bufp);
+#else
+ {
+ UINT handle;
+ handle = WinExec(bufp, SW_SHOW);
+ }
+#endif
+ return L_SUCCESS;
+}
+
+int Iexit(int argc, lvar_t * argv)
+{
+ longjmp(exitljbuf, 1);
+ return L_SUCCESS; /* NOT REACHED */
+}
+
+#ifdef FEATURE_DOT
+/* dot related functions */
+
+int Iparsegraphlabel(int argc, lvar_t * argv)
+{
+ rtno = D2Lparsegraphlabel(argv[0].o, argv[1].o);
+ return L_SUCCESS;
+}
+
+int Ireadgraph(int argc, lvar_t * argv)
+{
+ int ioi;
+
+ if ((ioi = Tgetnumber(argv[0].o)) < 0 || ioi >= ion)
+ return L_FAILURE;
+ if (argc == 2 && !T_ISTABLE(argv[1].o))
+ return L_FAILURE;
+ if (!(rtno = D2Lreadgraph(ioi, (argc == 2 ? argv[1].o : NULL))))
+ return L_FAILURE;
+ return L_SUCCESS;
+}
+
+int Iwritegraph(int argc, lvar_t * argv)
+{
+ int ioi;
+
+ if (!T_ISNUMBER(argv[0].o) || !T_ISTABLE(argv[1].o) ||
+ !T_ISINTEGER(argv[2].o))
+ return L_FAILURE;
+ if ((ioi = Tgetnumber(argv[0].o)) < 0 || ioi >= ion)
+ return L_FAILURE;
+ D2Lwritegraph(ioi, argv[1].o, Tgetinteger(argv[2].o));
+ return L_SUCCESS;
+}
+#endif
+
+static void growbufp(int newsize)
+{
+ if (!(bufp = realloc(bufp,
+ ((newsize + BUFINCR -
+ 1) / BUFINCR) * BUFINCR * BUFSIZE)))
+ panic(POS, "growbufp", "buf realloc failed");
+ bufn = ((newsize + BUFINCR - 1) / BUFINCR) * BUFINCR;
+}
--- /dev/null
+/* $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 _INTERNAL_H
+#define _INTERNAL_H
+ typedef struct Ifunc_t {
+ char *name;
+ int (*func) (int, Tonm_t *);
+ int min, max;
+ } Ifunc_t;
+
+ void Iinit(void);
+ void Iterm(void);
+ int Igetfunc(char *);
+
+ extern Ifunc_t Ifuncs[];
+ extern int Ifuncn;
+#endif /* _INTERNAL_H */
+
+#ifdef __cplusplus
+}
+#endif