pdfdir = $(pkgdatadir)/doc/pdf
+
AM_CPPFLAGS = \
- -I$(top_srcdir) \
- -I$(top_srcdir)/lib/expr \
- -I$(top_builddir)/lib/expr \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/lib/expr \
+ -I$(top_builddir)/lib/expr \
-I$(top_srcdir)/lib/vmalloc \
-I$(top_srcdir)/lib/sfio \
-I$(top_srcdir)/lib/ast \
-I$(top_srcdir)/lib/cgraph \
-I$(top_srcdir)/lib/cdt
+if ENABLE_STATIC
+bin_PROGRAMS = gvpr gvpr_static
+else
bin_PROGRAMS = gvpr
-noinst_PROGRAMS = mkdefs
-noinst_HEADERS = actions.h compile.h gprstate.h parse.h queue.h
+endif
+
man_MANS = gvpr.1
pdf_DATA = gvpr.1.pdf
-gvpr_SOURCES = actions.c compile.c gvpr.c gprstate.c parse.c queue.c
-
-gvpr_LDADD = \
- $(top_builddir)/lib/vmalloc/libvmalloc_C.la \
- $(top_builddir)/lib/sfio/libsfio_C.la \
- $(top_builddir)/lib/ingraphs/libingraphs_C.la \
- $(top_builddir)/lib/expr/libexpr_C.la \
- $(top_builddir)/lib/cgraph/libcgraph.la @MATH_LIBS@
-
-gvpr_DEPENDENCIES = \
- $(top_builddir)/lib/ast/libast_C.la
-
-$(gvpr_OBJECTS): gdefs.h
-
-mkdefs_SOURCES = mkdefs.c
-
-gdefs.h: $(top_srcdir)/cmd/gvpr/gprdata mkdefs
- ./mkdefs gdefs.h < $(top_srcdir)/cmd/gvpr/gprdata
+gvpr_SOURCES = gvprmain.c
+gvpr_CPPFLAGS = $(AM_CPPFLAGS)
+gvpr_LDADD = $(top_builddir)/lib/gvpr/libgvpr.la
gvpr.1.pdf: $(srcdir)/gvpr.1
- @GROFF@ -Tps -man $(srcdir)/gvpr.1 | @PS2PDF@ - - >gvpr.1.pdf
-EXTRA_DIST = $(man_MANS) $(pdf_DATA) lib Makefile.old gprdata mkdefs.c gdefs.h gvpr.vcproj
+gvpr_static_SOURCES = gvprmain.c
+gvpr_static_CPPFLAGS = $(AM_CPPFLAGS)
+gvpr_static_LDADD = \
+ $(top_builddir)/lib/gvpr/libgvpr_C.la \
+ $(top_builddir)/lib/expr/libexpr_C.la \
+ $(top_builddir)/lib/sfio/libsfio_C.la \
+ $(top_builddir)/lib/vmalloc/libvmalloc_C.la \
+ $(top_builddir)/lib/ingraphs/libingraphs_C.la \
+ $(top_builddir)/lib/ast/libast_C.la \
+ $(top_builddir)/lib/cgraph/libcgraph_C.la \
+ $(top_builddir)/lib/cdt/libcdt_C.la \
+ $(MATH_LIBS)
+
+EXTRA_DIST = $(man_MANS) $(pdf_DATA) Makefile.old gvpr.vcproj
-DISTCLEANFILES = $(pdf_DATA) gdefs.h mkdefs
+DISTCLEANFILES = $(pdf_DATA)
LOC_INCDIR=$(LOC_LIB)/include
LOC_LIBDIR=$(LOC_LIB)/lib
-INCS = -I. -I$(ROOT) -I$(LOC_INCDIR) -I$(LOC_LIB)/cgraph -I$(LOC_LIB)/cdt
+INCS = -I. -I$(ROOT) -I$(LOC_INCDIR) -I$(LOC_LIB)/gvpr -I$(LOC_LIB)/cgraph -I$(LOC_LIB)/cdt
DEFINES = -DHAVE_CONFIG_H -DUSE_CGRAPH
-OBJS = gvpr.o parse.o compile.o gprstate.o actions.o queue.o
+OBJS = gvprmain.o
-compile.o : gdefs.h
+LIBS = -L$(LOC_LIB)/gvpr -lgvpr \
+ -L$(LOC_LIB)/expr -lexpr \
+ -L$(LOC_LIB)/ast -last \
+ -L$(LOC_LIB)/sfio -lsfio \
+ -L$(LOC_LIB)/vmalloc -lvmalloc \
+ -L$(LOC_LIB)/ingraphs -lingraphs \
+ -L$(LOC_LIB)/cgraph -lcgraph \
+ -L$(LOC_LIB)/cdt -lcdt -lm
-gdefs.h : gprdata mkdefs
- mkdefs gdefs.h < gprdata
-
-mkdefs : mkdefs.o
- $(CC) $(LDFLAGS) mkdefs.o -o $@
-
-GLIBS = -L$(LOC_LIB)/cgraph -L$(LOC_LIB)/cdt -lcgraph -lcdt
-LIBS = -L$(LOC_LIBDIR) -lexpr -last -lvmalloc -lsfio -lingraphs $(GLIBS) -lm
-
-gvpr : $(OBJS) $(LOC_LIBDIR)/libexpr.a
+gvpr : $(OBJS)
$(CSLD) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
$(OBJS) : gdefs.h
$(INSTALL) gvpr.1 $(MANDIR)
clean :
- $(RM) core gdefs.h *.o
+ $(RM) core *.o
distclean : clean
- $(RM) mkdefs $(ALL)
+ $(RM) $(ALL)
--- /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 *
+**********************************************************/
+
+
+/*
+ * gvpr: graph pattern recognizer
+ *
+ * Written by Emden Gansner
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#else
+#include "compat_unistd.h"
+#endif
+#include "gvpr.h"
+
+#ifdef DEBUG
+#include "sfio.h"
+static ssize_t outfn (void* sp, const char *buf, size_t nbyte, void* dp)
+{
+ write (1, "<stdout> ", 8);
+ return write (1, buf, nbyte);
+}
+
+static ssize_t errfn (void* sp, const char *buf, size_t nbyte, void* dp)
+{
+ write (2, "<stderr> ", 8);
+ return write (2, buf, nbyte);
+}
+
+static int iofread(void *chan, char *buf, int bufsize)
+{
+ return read(sffileno((Sfio_t *) chan), buf, bufsize);
+}
+
+static int ioputstr(void *chan, char *str)
+{
+ return sfputr((Sfio_t *) chan, str, -1);
+}
+
+static int ioflush(void *chan)
+{
+ return sfsync((Sfio_t *) chan);
+}
+
+static Agiodisc_t gprIoDisc = { iofread, ioputstr, ioflush };
+
+static Agdisc_t gprDisc = { &AgMemDisc, &AgIdDisc, &gprIoDisc };
+
+int
+main (int argc, char* argv[])
+{
+ Agraph_t* gs[2];
+ Agraph_t* g = agread (sfstdin, &gprDisc);
+ int rv, i;
+ gvpropts opts;
+
+ gs[0] = g;
+ gs[1] = 0;
+ opts.ingraphs = gs;
+ opts.out = outfn;
+ opts.err = errfn;
+ opts.flags = GV_USE_OUTGRAPH;
+
+ rv = gvpr (argc, argv, &opts);
+
+ sfprintf (sfstderr, "rv %d\n", rv);
+ /* for (i = 0; i < opts.n_outgraphs; i++) */
+ /* agwrite (opts.outgraphs[i], sfstdout); */
+
+ rv = gvpr (argc, argv, &opts);
+
+ return rv;
+}
+
+#else
+int
+main (int argc, char* argv[])
+{
+ gvpropts opts;
+ opts.ingraphs = 0;
+ opts.out = 0;
+ opts.err = 0;
+ opts.flags = GV_USE_EXIT;
+
+ return gvpr (argc, argv, &opts);
+}
+
+#endif
+
lib/sparse/Makefile
lib/sfdpgen/Makefile
lib/osage/Makefile
+ lib/gvpr/Makefile
+ lib/gvpr/libgvpr.pc
lib/circogen/Makefile
lib/twopigen/Makefile
lib/patchwork/Makefile
SUBDIRS = cdt graph cgraph gd pathplan sfio vmalloc ast \
vpsc rbtree ortho sparse patchwork expr common \
pack gvc xdot ingraphs topfish glcomp \
- circogen dotgen fdpgen neatogen twopigen sfdpgen osage
+ circogen dotgen fdpgen neatogen twopigen sfdpgen osage gvpr
EXTRA_DIST = Makefile.old gvc.vcproj gvc.def
--- /dev/null
+# $Id$Revision:
+## Process this file with automake to produce Makefile.in
+
+pkgconfigdir = $(libdir)/pkgconfig
+
+GVPR_VERSION="1:0:0"
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/lib/expr \
+ -I$(top_builddir)/lib/expr \
+ -I$(top_srcdir)/lib/vmalloc \
+ -I$(top_srcdir)/lib/sfio \
+ -I$(top_srcdir)/lib/ast \
+ -I$(top_srcdir)/lib/ingraphs \
+ -I$(top_srcdir)/lib/cgraph \
+ -I$(top_srcdir)/lib/cdt
+
+pkginclude_HEADERS = gvpr.h
+noinst_PROGRAMS = mkdefs
+noinst_HEADERS = actions.h compile.h gprstate.h parse.h queue.h
+noinst_LTLIBRARIES = libgvpr_C.la
+lib_LTLIBRARIES = libgvpr.la
+pkgconfig_DATA = libgvpr.pc
+
+libgvpr_C_la_SOURCES = actions.c compile.c gvpr.c gprstate.c parse.c queue.c
+$(libgvpr_C_la_OBJECTS): gdefs.h
+libgvpr_C_la_DEPENDENCIES = \
+ $(top_builddir)/lib/expr/libexpr_C.la \
+ $(top_builddir)/lib/ingraphs/libingraphs_C.la
+
+
+libgvpr_la_LDFLAGS = -version-info $(GVPR_VERSION) -no-undefined
+libgvpr_la_SOURCES = $(libgvpr_C_la_SOURCES)
+libgvpr_la_LIBADD = $(libgvpr_C_la_LIBADD) \
+ $(top_builddir)/lib/ingraphs/libingraphs_C.la \
+ $(top_builddir)/lib/expr/libexpr_C.la \
+ $(top_builddir)/lib/cdt/libcdt.la \
+ $(top_builddir)/lib/cgraph/libcgraph.la \
+ $(MATH_LIBS)
+libgvpr_la_DEPENDENCIES = $(libgvpr_C_la_DEPENDENCIES)
+
+mkdefs_SOURCES = mkdefs.c
+
+gdefs.h: $(top_srcdir)/lib/gvpr/gprdata mkdefs
+ ./mkdefs gdefs.h < $(top_srcdir)/lib/gvpr/gprdata
+
+EXTRA_DIST = $(man_MANS) $(pdf_DATA) lib Makefile.old gprdata mkdefs.c gdefs.h gvpr.vcproj
+
+DISTCLEANFILES = $(pdf_DATA) gdefs.h mkdefs
--- /dev/null
+# gvpr library make file
+# Written by Emden R. Gansner (23 June 2009)
+ALL = libgvpr.a
+all : $(ALL)
+ROOT=../..
+include $(ROOT)/Config.mk
+include $(ROOT)/makearch/$(ARCH)
+
+LOC_LIB=$(ROOT)/lib
+LOC_INCDIR=$(LOC_LIB)/include
+LOC_LIBDIR=$(LOC_LIB)/lib
+
+INCS = -I. -I$(ROOT) -I$(LOC_INCDIR) -I$(LOC_LIB)/cgraph -I$(LOC_LIB)/cdt \
+ -I$(LOC_LIB)/expr -I$(LOC_LIB)/ast -I$(LOC_LIB)/sfio -I$(LOC_LIB)/vmalloc -I$(LOC_LIB)/ingraphs
+
+DEFINES = -DHAVE_CONFIG_H -DUSE_CGRAPH
+
+OBJS = gvpr.o parse.o compile.o gprstate.o actions.o queue.o trie.o
+
+
+compile.o : gdefs.h
+
+gdefs.h : gprdata mkdefs
+ mkdefs gdefs.h < gprdata
+
+mkdefs : mkdefs.o
+ $(CC) $(LDFLAGS) mkdefs.o -o $@
+
+GLIBS = -L$(LOC_LIB)/cgraph -L$(LOC_LIB)/cdt -lcgraph -lcdt
+LIBS = -L$(LOC_LIBDIR) -lexpr -last -lvmalloc -lsfio -lingraphs $(GLIBS) -lm
+
+gvpr : $(OBJS) $(LOC_LIBDIR)/libexpr.a
+ $(CSLD) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+libgvpr.a: $(OBJS)
+ $(RM) libgvpr.a
+ $(AR) cr libgvpr.a $(OBJS)
+ $(RANLIB) libgvpr.a
+
+install: libgvpr.a
+ $(MKPATH) $(LIBDIR)
+ $(INSTALL) libpgvpr.a $(LIBDIR)
+
+
+$(OBJS) : gdefs.h
+
+clean :
+ $(RM) core gdefs.h *.o
+
+distclean : clean
+ $(RM) mkdefs $(ALL)
char *name = agnameof(obj);
if ((kind != AGRAPH) && !g) {
- error(ERROR_FATAL, "NULL graph with non-graph object in copy()");
+ exerror("NULL graph with non-graph object in copy()");
return 0;
}
return 0;
for (t = agfstnode(g); t; t = agnxtnode(g, t)) {
newt = agnode(tgt, agnameof(t), 0);
- if (!newt)
- error(ERROR_PANIC, "node %s not found in cloned graph %s",
+ if (!newt) {
+ exerror("node %s not found in cloned graph %s",
agnameof(t), agnameof(tgt));
- agsubnode(ng, newt, 1);
+ return 0;
+ }
+ else
+ agsubnode(ng, newt, 1);
}
for (t = agfstnode(g); t; t = agnxtnode(g, t)) {
for (e = agfstout(g, t); e; e = agnxtout(g, e)) {
newe = mapEdge (emap, e);
- if (!newe)
- error(ERROR_PANIC,
- "edge (%s,%s)[%s] not found in cloned graph %s",
+ if (!newe) {
+ exerror("edge (%s,%s)[%s] not found in cloned graph %s",
agnameof(agtail(e)), agnameof(aghead(e)),
agnameof(e), agnameof(tgt));
- agsubedge(ng, newe, 1);
+ return 0;
+ }
+ else
+ agsubedge(ng, newe, 1);
}
}
for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) {
if (!cloneSubg(ng, sg, emap)) {
- error(ERROR_FATAL, "error cloning subgraph %s from graph %s",
+ exerror("error cloning subgraph %s from graph %s",
agnameof(sg), agnameof(g));
+ return 0;
}
}
return ng;
for (t = agfstnode(src); t; t = agnxtnode(src, t)) {
if (!copy(tgt, OBJ(t))) {
- error(ERROR_FATAL, "error cloning node %s from graph %s",
+ exerror("error cloning node %s from graph %s",
agnameof(t), agnameof(src));
}
}
for (t = agfstnode(src); t; t = agnxtnode(src, t)) {
for (e = agfstout(src, t); e; e = agnxtout(src, e)) {
if (!(ne = (Agedge_t*)copy(tgt, OBJ(e)))) {
- error(ERROR_FATAL,
- "error cloning edge (%s,%s)[%s] from graph %s",
+ exerror("error cloning edge (%s,%s)[%s] from graph %s",
agnameof(agtail(e)), agnameof(aghead(e)),
agnameof(e), agnameof(src));
+ return;
}
ep->key = e;
ep->val = ne;
}
for (sg = agfstsubg(src); sg; sg = agnxtsubg(sg)) {
if (!cloneSubg(tgt, sg, emap)) {
- error(ERROR_FATAL, "error cloning subgraph %s from graph %s",
+ exerror("error cloning subgraph %s from graph %s",
agnameof(sg), agnameof(src));
}
}
char *name = agnameof(obj);
if ((kind != AGRAPH) && !g) {
- error(ERROR_FATAL, "NULL graph with non-graph object in clone()");
+ exerror("NULL graph with non-graph object in clone()");
return 0;
}
Sfio_t *fp;
if (!f) {
- error(ERROR_FATAL, "NULL string passed to writeG");
+ exerror("NULL string passed to writeG");
return 1;
}
fp = sfopen(0, f, "w");
if (!fp) {
- error(ERROR_FATAL, "Could not open %s for writing in writeG", f);
+ exerror("Could not open %s for writing in writeG", f);
return 1;
}
rv = agwrite(g, fp);
Sfio_t *fp;
if (!f) {
- error(ERROR_FATAL, "NULL string passed to readG");
+ exerror("NULL string passed to readG");
return 0;
}
fp = sfopen(0, f, "r");
if (!fp) {
- error(ERROR_FATAL, "Could not open %s for reading in readG", f);
+ exerror("Could not open %s for reading in readG", f);
return 0;
}
gp = readG(fp);
if (!ex->file[idx])
break;
if (idx == elementsof(ex->file)) {
- error(ERROR_FATAL, "openF: no available descriptors");
+ exerror("openF: no available descriptors");
return -1;
}
ex->file[idx] = sfopen(0, fname, mode);
int rv;
if ((0 <= fd) && (fd <= 2)) {
- error(ERROR_FATAL, "closeF: cannot close standard stream %d", fd);
+ exerror("closeF: cannot close standard stream %d", fd);
return -1;
}
if (!ex->file[fd]) {
- error(ERROR_FATAL, "closeF: stream %d not open", fd);
+ exerror("closeF: stream %d not open", fd);
return -1;
}
rv = sfclose(ex->file[fd]);
#include <gdefs.h>
+#include "ctype.h"
+#include "trie.c"
+
#define BITS_PER_BYTE 8
#ifdef HAVE_INTPTR_T
#define INT2PTR(t,v) ((t)(intptr_t)(v))
x->data.variable.dyna->data.variable.dyna->data.
constant.value.integer);
if (!ptr) {
- error(ERROR_FATAL, "null reference %s in expression %s.%s",
+ exerror("null reference %s in expression %s.%s",
ref->symbol->name, ref->symbol->name, deparse(pgm, x,
- state->
- tmp));
+ state->tmp));
return ptr;
} else
return deref(pgm, x, ref->next, (Agobj_t *) ptr, state);
break;
case M_head:
if (!objp && !(objp = state->curobj)) {
- error(ERROR_WARNING, "Current object $ not defined");
+ exerror("Current object $ not defined");
return 0;
}
if (ISEDGE(objp))
return deref(pgm, x, ref->next,
(Agobj_t *) AGHEAD((Agedge_t *) objp), state);
else
- error(ERROR_FATAL, "head of non-edge");
+ exerror("head of non-edge");
break;
case M_tail:
if (!objp && !(objp = state->curobj)) {
- error(ERROR_FATAL, "Current object $ not defined");
+ exerror("Current object $ not defined");
return 0;
}
if (ISEDGE(objp))
return deref(pgm, x, ref->next,
(Agobj_t *) AGTAIL((Agedge_t *) objp), state);
else
- error(ERROR_FATAL, "tail of non-edge %x", objp);
+ exerror("tail of non-edge %x", objp);
break;
default:
- error(ERROR_WARNING, "%s : illegal reference",
+ exerror("%s : illegal reference",
ref->symbol->name);
- return 0;
break;
}
return 0;
}
+/* assignable:
+ * Check that attribute is not a read-only, pseudo-attribute.
+ * Return 1 if okay; fatal otherwise.
+ */
+static int
+assignable (Agobj_t *objp, unsigned char* name)
+{
+ unsigned int ch;
+ int rv;
+ unsigned char* p = name;
+
+ TFA_Init();
+ while ((TFA_State >= 0) && (ch = *p)) {
+ TFA_Advance(ch & ~127 ? 127 : ch);
+ p++;
+ }
+ rv = TFA_Definition();
+ if (rv < 0) return 1;
+
+ switch (AGTYPE(objp)) {
+ case AGRAPH :
+ if (rv & Y(G))
+ exerror("Cannot assign to pseudo-graph attribute %s", name);
+ break;
+ case AGNODE :
+ if (rv & Y(V))
+ exerror("Cannot assign to pseudo-node attribute %s", name);
+ break;
+ default : /* edge */
+ if (rv & Y(E))
+ exerror("Cannot assign to pseudo-edge attribute %s", name);
+ break;
+ }
+ return 1;
+}
+
/* setattr:
* Set object's attribute name to val.
* Initialize attribute if necessary.
if (AGTYPE(objp) == AGNODE)
v->integer = agdegree(agroot(objp), (Agnode_t *) objp, 1, 0);
else {
- error(ERROR_FATAL, "indegree of non-node");
+ exerror("indegree of non-node");
return -1;
}
break;
if (AGTYPE(objp) == AGNODE)
v->integer = agdegree(agroot(objp), (Agnode_t *) objp, 0, 1);
else {
- error(ERROR_FATAL, "outdegree of non-node");
+ exerror("outdegree of non-node");
return -1;
}
break;
if (AGTYPE(objp) == AGNODE)
v->integer = agdegree(agroot(objp), (Agnode_t *) objp, 1, 1);
else {
- error(ERROR_FATAL, "degree of non-node");
+ exerror("degree of non-node");
return -1;
}
break;
if (AGTYPE(objp) == AGRAPH)
v->integer = PTR2INT(agparent((Agraph_t *) objp));
else {
- error(ERROR_FATAL, "parent of non-graph");
+ exerror("parent of non-graph");
return -1;
}
break;
if (AGTYPE(objp) == AGRAPH)
v->integer = agnedges((Agraph_t *) objp);
else {
- error(ERROR_FATAL, "n_edges of non-graph");
+ exerror("n_edges of non-graph");
return -1;
}
break;
if (AGTYPE(objp) == AGRAPH)
v->integer = agnnodes((Agraph_t *) objp);
else {
- error(ERROR_FATAL, "n_nodes of non-graph");
+ exerror("n_nodes of non-graph");
return -1;
}
break;
if (AGTYPE(objp) == AGRAPH)
v->integer = agisdirected((Agraph_t *) objp);
else {
- error(ERROR_FATAL, "directed of non-graph");
+ exerror("directed of non-graph");
return -1;
}
break;
if (AGTYPE(objp) == AGRAPH)
v->integer = agisstrict((Agraph_t *) objp);
else {
- error(ERROR_FATAL, "strict of non-graph");
+ exerror("strict of non-graph");
return -1;
}
break;
Agsym_t *gsym = agattrsym(objp, sym->name);
if (!gsym) {
gsym = agattr(agroot(agraphof(objp)), AGTYPE(objp), sym->name, "");
- error(ERROR_WARNING, "Using value of uninitialized attribute \"%s\" of %s \"%s\"", sym->name, kindOf (objp), nameOf(pgm, objp));
+ error(ERROR_WARNING, "Using value of uninitialized %s attribute \"%s\" of \"%s\"", kindOf (objp), sym->name, nameOf(pgm, objp));
}
v->string = agxget(objp, gsym);
}
static char *getArg(int n, Gpr_t * state)
{
if (n >= state->argc) {
- error(ERROR_FATAL, "program references ARGV[%d] - undefined", n);
+ exerror("program references ARGV[%d] - undefined", n);
+ return 0;
}
return (state->argv[n]);
}
kind = AGNODE;
break;
default :
- error(ERROR_FATAL, "Unknown kind \"%s\" passed to %s()", k, fn);
+ exerror("Unknown kind \"%s\" passed to %s()", k, fn);
+ kind = 0;
break;
}
return kind;
if (name) {
sym = agattr (gp, kind, name, 0);
if (!sym) {
- error(ERROR_FATAL, "Third argument \"%s\" in nxtAttr() must be the name of an existing attribute", name);
+ exerror("Third argument \"%s\" in nxtAttr() must be the name of an existing attribute", name);
+ return "";
}
}
/* getval:
* Return value associated with gpr identifier.
*/
-Extype_t
+static Extype_t
getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref,
void *env, int elt, Exdisc_t * disc)
{
case F_kindof:
objp = INT2PTR(Agobj_t *, args[0].integer);
if (!objp) {
- error(ERROR_FATAL, "NULL object passed to kindOf()");
+ exerror("NULL object passed to kindOf()");
+ v.string = 0;
} else switch (AGTYPE(objp)) {
case AGRAPH :
v.string = "G";
objp = INT2PTR(Agobj_t *, args[0].integer);
name = args[1].string;
if (!objp) {
- error(ERROR_FATAL, "NULL object passed to aget()/hasAttr()");
+ exerror("NULL object passed to aget()/hasAttr()");
+ v.integer = 0;
} else if (!name) {
- error(ERROR_FATAL, "NULL name passed to aget()/hasAttr()");
+ exerror("NULL name passed to aget()/hasAttr()");
+ v.integer = 0;
}
else {
Agsym_t *gsym = agattrsym(objp, name);
else {
if (!gsym) {
gsym = agattr(agroot(agraphof(objp)), AGTYPE(objp), name, "");
- error(ERROR_WARNING, "Using value of uninitialized attribute \"%s\" of %s \"%s\" in aget()", name, kindOf (objp), nameOf(pgm, objp));
+ error(ERROR_WARNING, "Using value of %s uninitialized attribute \"%s\" of \"%s\" in aget()", kindOf (objp), name, nameOf(pgm, objp));
}
v.string = agxget(objp, gsym);
}
if (gp) {
char* kind = args[1].string;
if (!kind) {
- error(ERROR_FATAL,"NULL kind passed to fstAttr()");
+ error(ERROR_ERROR,"NULL kind passed to fstAttr()");
+ v.string = 0;
}
else {
v.string = nxtAttr (gp, kind, NULL);
}
} else {
- error(ERROR_FATAL, "NULL graph passed to fstAttr()");
+ exerror("NULL graph passed to fstAttr()");
+ v.string = 0;
}
break;
case F_nxtattr:
char* kind = args[1].string;
char* name = args[2].string;
if (!name) {
- error(ERROR_FATAL,"NULL name passed to %s", sym->name);
+ exerror("NULL name passed to %s", sym->name);
+ v.string = 0;
}
else if (!kind) {
- error(ERROR_FATAL,"NULL kind passed to %s", sym->name);
+ exerror("NULL kind passed to %s", sym->name);
+ v.string = 0;
}
else if (sym->index == F_isattr) {
v.integer = (agattr(gp, toKind (kind, sym->name), name, 0) != NULL);
v.string = getDfltAttr(gp, kind, name);
}
} else {
- error(ERROR_FATAL, "NULL graph passed to %s", sym->name);
+ exerror("NULL graph passed to %s", sym->name);
+ v.string = 0;
}
break;
case F_canon:
v.integer = match(args[0].string, args[1].string);
break;
default:
- error(ERROR_FATAL, "unknown function call: %s", sym->name);
+ exerror("unknown function call: %s", sym->name);
}
return v;
} else if (elt == EX_ARRAY) {
v.string = getArg(args[0].integer, state);
break;
default:
- error(ERROR_FATAL, "unknown array name: %s", sym->name);
+ exerror("unknown array name: %s", sym->name);
+ v.string = 0;
}
return v;
}
if (ref) {
objp = deref(pgm, node, ref, 0, state);
if (!objp)
- error(ERROR_FATAL, "null reference in expression %s",
+ exerror("null reference in expression %s",
deparse(pgm, node, state->tmp));
} else if ((sym->lex == ID) && (sym->index <= LAST_V)) {
switch (sym->index) {
return v;
} else {
objp = state->curobj;
- if (!objp)
- error(ERROR_FATAL,
- "current object $ not defined as reference for %s",
+ if (!objp) {
+ exerror("current object $ not defined as reference for %s",
deparse(pgm, node, state->tmp));
+ }
}
- if (lookup(pgm, objp, sym, &v, state))
- error(ERROR_FATAL, "in expression %s",
- deparse(pgm, node, state->tmp));
+ if (objp) {
+ if (lookup(pgm, objp, sym, &v, state)) {
+ exerror("in expression %s", deparse(pgm, node, state->tmp));
+ v.integer = 0;
+ }
+ }
+ else
+ v.integer = 0;
return v;
}
* Return -1 if not allowed.
* Assume already type correct.
*/
-int
+static int
setval(Expr_t * pgm, Exnode_t * x, Exid_t * sym, Exref_t * ref,
void *env, int elt, Extype_t v, Exdisc_t * disc)
{
if (ref) {
objp = deref(pgm, x, ref, 0, state);
if (!objp) {
- error(ERROR_FATAL, "in expression %s.%s",
+ exerror("in expression %s.%s",
ref->symbol->name, deparse(pgm, x, state->tmp));
return -1;
}
return rv;
} else {
objp = state->curobj;
- if (!objp)
- error(ERROR_FATAL,
- "current object $ undefined in expression %s",
+ if (!objp) {
+ exerror("current object $ undefined in expression %s",
deparse(pgm, x, state->tmp));
+ return -1;
+ }
}
-
+ assignable (objp, (unsigned char*)(sym->name));
return setattr(objp, sym->name, v.string);
}
* The grammar has been altered to disallow the first 3.
* Type check expressions; return value unused.
*/
-Extype_t
+static Extype_t
refval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref,
char *str, int elt, Exdisc_t * disc)
{
break;
}
} else {
- if (!typeChkExp(ref, sym))
+ if (!typeChkExp(ref, sym)) {
+ Gpr_t *state = (Gpr_t *) (disc->user);
exerror("type error using %s",
- deparse(pgm, node, sfstropen()));
+ deparse(pgm, node, state->tmp));
+ }
v = exzero(node->type);
}
return v;
}
-#ifdef OLD
-static void cvtError(Exid_t * xref, char *msg)
-{
- if (xref)
- error(ERROR_FATAL, "%s: %s", xref->name, msg);
- else
- error(ERROR_FATAL, "%s", msg);
-}
-#endif
-
/* binary:
* Evaluate (l ex->op r) producing a value of type ex->type,
* stored in l.
} else if (!strcmp(sfx, "prepostrev")) {
rt = TV_prepostrev;
} else
- error(ERROR_FATAL, "illegal string \"%s\" for type tvtype_t", s);
+ exerror("illegal string \"%s\" for type tvtype_t", s);
} else
- error(ERROR_FATAL, "illegal string \"%s\" for type tvtype_t", s);
+ exerror("illegal string \"%s\" for type tvtype_t", s);
return rt;
}
* Return -1 if conversion cannot be done, 0 otherwise.
* If arg is > 0, conversion unnecessary; just report possibility.
*/
-int stringOf(Expr_t * prog, register Exnode_t * x, int arg)
+static int stringOf(Expr_t * prog, register Exnode_t * x, int arg)
{
Agobj_t *objp;
+ int rv = 0;
if (arg)
return 0;
if (x->type == T_tvtyp) {
- x->data.constant.value.string =
- tvtypeToStr (x->data.constant.value.integer);
+ if (!(x->data.constant.value.string =
+ tvtypeToStr (x->data.constant.value.integer)))
+ rv = -1;
} else {
objp = INT2PTR(Agobj_t *, x->data.constant.value.integer);
- if (!objp)
+ if (!objp) {
exerror("cannot generate name for NULL %s",
typeName(prog, x->type));
- x->data.constant.value.string = nameOf(prog, objp);
+ rv = -1;
+ }
+ else
+ x->data.constant.value.string = nameOf(prog, objp);
}
x->type = STRING;
return 0;
* Use #ifdef OLD to remove graph object conversion to strings,
* as this seemed to dangerous.
*/
-int
+static int
convert(Expr_t * prog, register Exnode_t * x, int type,
register Exid_t * xref, int arg, Exdisc_t * disc)
{
else if (validTVT(x->data.constant.value.integer))
ret = 0;
else
- error(ERROR_FATAL, "Integer value %d not legal for type tvtype_t",
+ exerror("Integer value %d not legal for type tvtype_t",
x->data.constant.value.integer);
}
/* in case libexpr hands us the trivial case */
Exdisc_t *dp;
dp = newof(0, Exdisc_t, 1, 0);
- if (!dp)
- error(ERROR_FATAL,
+ if (!dp) {
+ error(ERROR_ERROR,
"could not create libexp discipline: out of memory");
+ return 0;
+ }
dp->version = EX_VERSION;
- dp->flags = EX_CHARSTRING | EX_FATAL | EX_UNDECLARED;
+ dp->flags = EX_CHARSTRING | EX_UNDECLARED;
dp->symbols = symbols;
dp->convertf = convert;
dp->stringof = stringOf;
dp->binaryf = binary;
dp->typename = typeName;
- dp->errorf = (Exerror_f) errorf;
+ if (state->errf)
+ dp->errorf = state->errf;
+ else
+ dp->errorf = (Exerror_f) errorf;
dp->keyf = keyval;
dp->getf = getval;
dp->reff = refval;
dp->setf = setval;
dp->matchf = matchval;
+ dp->exitf = state->exitf;
dp->types = a2t;
dp->user = state;
+ state->dp = dp; /* dp is freed when state is freed */
+
return dp;
}
static Exnode_t *compile(Expr_t * prog, char *src, char *input, int line,
char *lbl, char *sfx, int kind)
{
- Exnode_t *e;
+ Exnode_t *e = 0;
Sfio_t *sf;
Sfio_t *prefix;
+ int rv;
/* create input stream */
if (sfx) {
line--;
}
- /* prog is set to exit on errors */
if (!src)
src = "<command line>";
- excomp(prog, src, line, 0, sf);
+ rv = excomp(prog, src, line, 0, sf);
sfclose(sf);
- e = exexpr(prog, lbl, NiL, kind);
+ if (rv >= 0 && (getErrorErrors() == 0))
+ e = exexpr(prog, lbl, NiL, kind);
return e;
}
gp = exnoncast(gp);
if (gp && exisAssign(gp)) {
if (src) {
-#ifdef GVDLL
setErrorFileLine (src, line);
-#else
- error_info.file = src;
- error_info.line = line;
-#endif
}
error(ERROR_WARNING, "assignment used as bool in guard");
}
sfprintf(tmps, "%s_g%d", lbl, i);
cs[i].guard = compile(prog, src, sp->guard, sp->gstart,
sfstruse(tmps), 0, INTEGER);
+ if (getErrorErrors()) break;
checkGuard(cs[i].guard, src, sp->gstart);
}
if (sp->action) {
sfprintf(tmps, "%s_a%d", lbl, i);
cs[i].action = compile(prog, src, sp->action, sp->astart,
sfstruse(tmps), 0, INTEGER);
+ if (getErrorErrors()) break;
}
sp = sp->next;
}
comp_prog *compileProg(parse_prog * inp, Gpr_t * state, int flags)
{
comp_prog *p;
- Exdisc_t *dp;
Sfio_t *tmps = sfstropen();
char *endg_sfx = 0;
assert(BITS_PER_BYTE * sizeof(tctype) >= (1 << TBITS));
p = newof(0, comp_prog, 1, 0);
- if (!p)
- error(ERROR_FATAL,
+ if (!p) {
+ error(ERROR_ERROR,
"could not create compiled program: out of memory");
+ goto finish;
+ }
if (flags) {
endg_sfx = doFlags(flags, tmps);
endg_sfx = 0;
}
- dp = initDisc(state);
- p->prog = exopen(dp);
+ if (!(initDisc(state)))
+ goto finish;
+
+ exinit();
+ if (!(p->prog = exopen(state->dp)))
+ goto finish;
codePhase = 0;
if (inp->begin_stmt) {
p->begin_stmt = compile(p->prog, inp->source, inp->begin_stmt,
inp->l_begin, 0, 0, VOID);
+ if (getErrorErrors())
+ goto finish;
}
codePhase = 1;
tchk[V_this][1] = Y(G);
p->begg_stmt = compile(p->prog, inp->source, inp->begg_stmt,
inp->l_beging, "_begin_g", 0, VOID);
+ if (getErrorErrors())
+ goto finish;
}
codePhase = 2;
p->n_nstmts = inp->n_nstmts;
p->node_stmts = mkStmts(p->prog, inp->source, inp->node_stmts,
inp->n_nstmts, "_nd");
+ if (getErrorErrors())
+ goto finish;
}
codePhase = 3;
p->n_estmts = inp->n_estmts;
p->edge_stmts = mkStmts(p->prog, inp->source, inp->edge_stmts,
inp->n_estmts, "_eg");
+ if (getErrorErrors())
+ goto finish;
}
codePhase = 4;
tchk[V_this][1] = Y(G);
p->endg_stmt = compile(p->prog, inp->source, inp->endg_stmt,
inp->l_endg, "_end_g", endg_sfx, VOID);
+ if (getErrorErrors())
+ goto finish;
}
codePhase = 5;
symbols[0].type = T_obj;
p->end_stmt = compile(p->prog, inp->source, inp->end_stmt,
inp->l_end, "_end_", 0, VOID);
+ if (getErrorErrors())
+ goto finish;
+ }
+ setErrorLine (0); /* execution errors have no line numbers */
+
+ finish:
+ if (getErrorErrors()) {
+ freeCompileProg (p);
+ p = 0;
}
+
sfclose(tmps);
-#ifdef GVDLL
- setErrorLine (0);
-#else
- error_info.line = 0; /* execution errors have no line numbers */
-#endif
return p;
}
+void
+freeCompileProg (comp_prog *p)
+{
+ if (!p) return;
+
+ exclose (p->prog, 1);
+ free (p->node_stmts);
+ free (p->edge_stmts);
+ free (p);
+}
+
/* walksGraph;
* Returns true if program actually has node or edge statements.
*/
{
Agraph_t *g;
+#ifdef GVDLL
+ gprDisc.mem = &AgMemDisc;
+ gprDisc.id = &AgIdDisc;
+#endif
g = agopen(name, desc, &gprDisc);
if (g)
agbindrec(g, UDATA, sizeof(gdata), 0);
agbindrec(ep, UDATA, sizeof(edata), 0);
return ep;
}
+
#define SRCOUT 0x1
#define INDUCE 0x2
+#define CLONE 0x4
typedef struct {
Expr_t *prog;
} comp_prog;
extern comp_prog *compileProg(parse_prog *, Gpr_t *, int);
+ extern void freeCompileProg (comp_prog *p);
extern int usesGraph(comp_prog *);
extern int walksGraph(comp_prog *);
extern Agraph_t *readG(Sfio_t * fp);
--- /dev/null
+#ifndef GDEFS_H
+#define GDEFS_H
+
+/* generated by mkdefs; do not edit */
+
+#define Y(i) (1<<(i))
+
+#define V 0x4 /* NODE */
+#define E 0x5 /* EDGE */
+#define G 0x6 /* GRAPH */
+#define O 0x7 /* OBJECT */
+#define TV 0x8 /* TV_ */
+#define YALL (Y(V)|Y(E)|Y(G))
+
+#define V_this 1
+#define V_thisg 2
+#define V_targt 3
+#define V_outgraph 4
+#define V_tgtname 5
+#define V_infname 6
+#define V_travroot 7
+#define V_travtype 8
+#define V_ARGC 9
+#define M_degree 10
+#define M_head 11
+#define M_tail 12
+#define M_name 13
+#define M_indegree 14
+#define M_outdegree 15
+#define M_root 16
+#define M_parent 17
+#define M_n_edges 18
+#define M_n_nodes 19
+#define M_directed 20
+#define M_strict 21
+#define T_node 22
+#define T_edge 23
+#define T_graph 24
+#define T_obj 25
+#define T_tvtyp 26
+#define A_ARGV 27
+#define F_graph 28
+#define F_subg 29
+#define F_issubg 30
+#define F_fstsubg 31
+#define F_nxtsubg 32
+#define F_node 33
+#define F_addnode 34
+#define F_fstnode 35
+#define F_nxtnode 36
+#define F_nxtnodesg 37
+#define F_isnode 38
+#define F_issubnode 39
+#define F_indegree 40
+#define F_outdegree 41
+#define F_degree 42
+#define F_isin 43
+#define F_edge 44
+#define F_edgesg 45
+#define F_addedge 46
+#define F_fstout 47
+#define F_nxtout 48
+#define F_fstin 49
+#define F_nxtin 50
+#define F_fstedge 51
+#define F_nxtedge 52
+#define F_fstoutsg 53
+#define F_nxtoutsg 54
+#define F_fstinsg 55
+#define F_nxtinsg 56
+#define F_fstedgesg 57
+#define F_nxtedgesg 58
+#define F_compof 59
+#define F_kindof 60
+#define F_index 61
+#define F_rindex 62
+#define F_isedge 63
+#define F_isedgesg 64
+#define F_issubedge 65
+#define F_length 66
+#define F_match 67
+#define F_write 68
+#define F_writeg 69
+#define F_readg 70
+#define F_fwriteg 71
+#define F_freadg 72
+#define F_openf 73
+#define F_closef 74
+#define F_readl 75
+#define F_induce 76
+#define F_isdirect 77
+#define F_isstrict 78
+#define F_delete 79
+#define F_clone 80
+#define F_copy 81
+#define F_copya 82
+#define F_lock 83
+#define F_nnodes 84
+#define F_nedges 85
+#define F_sqrt 86
+#define F_cos 87
+#define F_sin 88
+#define F_atan2 89
+#define F_exp 90
+#define F_pow 91
+#define F_log 92
+#define F_min 93
+#define F_max 94
+#define F_sys 95
+#define F_xof 96
+#define F_yof 97
+#define F_llof 98
+#define F_urof 99
+#define F_canon 100
+#define F_get 101
+#define F_set 102
+#define F_dget 103
+#define F_dset 104
+#define F_hasattr 105
+#define F_isattr 106
+#define F_fstattr 107
+#define F_nxtattr 108
+#define C_flat 109
+#define C_ne 110
+#define C_en 111
+#define C_bfs 112
+#define C_dfs 113
+#define C_fwd 114
+#define C_rev 115
+#define C_postdfs 116
+#define C_postfwd 117
+#define C_postrev 118
+#define C_prepostdfs 119
+#define C_prepostfwd 120
+#define C_prepostrev 121
+#define C_null 122
+
+#define LAST_V 9
+#define LAST_M 21
+#define MINNAME 1
+#define MAXNAME 122
+
+static Exid_t symbols[] = {
+ EX_ID ( "$", ID, V_this, T_obj, 0),
+ EX_ID ( "$G", ID, V_thisg, T_graph, 0),
+ EX_ID ( "$T", ID, V_targt, T_graph, 0),
+ EX_ID ( "$O", ID, V_outgraph, T_graph, 0),
+ EX_ID ( "$tgtname", ID, V_tgtname, STRING, 0),
+ EX_ID ( "$F", ID, V_infname, STRING, 0),
+ EX_ID ( "$tvroot", ID, V_travroot, T_node, 0),
+ EX_ID ( "$tvtype", ID, V_travtype, T_tvtyp, 0),
+ EX_ID ( "ARGC", ID, V_ARGC, INTEGER, 0),
+ EX_ID ( "degree", ID, M_degree, INTEGER, 0),
+ EX_ID ( "head", ID, M_head, T_node, 0),
+ EX_ID ( "tail", ID, M_tail, T_node, 0),
+ EX_ID ( "name", ID, M_name, STRING, 0),
+ EX_ID ( "indegree", ID, M_indegree, INTEGER, 0),
+ EX_ID ( "outdegree", ID, M_outdegree, INTEGER, 0),
+ EX_ID ( "root", ID, M_root, T_graph, 0),
+ EX_ID ( "parent", ID, M_parent, T_graph, 0),
+ EX_ID ( "n_edges", ID, M_n_edges, INTEGER, 0),
+ EX_ID ( "n_nodes", ID, M_n_nodes, INTEGER, 0),
+ EX_ID ( "directed", ID, M_directed, INTEGER, 0),
+ EX_ID ( "strict", ID, M_strict, INTEGER, 0),
+ EX_ID ( "node_t", DECLARE, T_node, T_node, 0),
+ EX_ID ( "edge_t", DECLARE, T_edge, T_edge, 0),
+ EX_ID ( "graph_t", DECLARE, T_graph, T_graph, 0),
+ EX_ID ( "obj_t", DECLARE, T_obj, T_obj, 0),
+ EX_ID ( "tvtype_t", DECLARE, T_tvtyp, T_tvtyp, 0),
+ EX_ID ( "ARGV", ARRAY, A_ARGV, S|A(1,I), 0),
+ EX_ID ( "graph", FUNCTION, F_graph, G|A(1,S)|A(2,S), 0),
+ EX_ID ( "subg", FUNCTION, F_subg, G|A(1,G)|A(2,S), 0),
+ EX_ID ( "isSubg", FUNCTION, F_issubg, G|A(1,G)|A(2,S), 0),
+ EX_ID ( "fstsubg", FUNCTION, F_fstsubg, G|A(1,G), 0),
+ EX_ID ( "nxtsubg", FUNCTION, F_nxtsubg, G|A(1,G), 0),
+ EX_ID ( "node", FUNCTION, F_node, V|A(1,G)|A(2,S), 0),
+ EX_ID ( "subnode", FUNCTION, F_addnode, V|A(1,G)|A(2,V), 0),
+ EX_ID ( "fstnode", FUNCTION, F_fstnode, V|A(1,G), 0),
+ EX_ID ( "nxtnode", FUNCTION, F_nxtnode, V|A(1,V), 0),
+ EX_ID ( "nxtnode_sg", FUNCTION, F_nxtnodesg, V|A(1,G)|A(2,V), 0),
+ EX_ID ( "isNode", FUNCTION, F_isnode, V|A(1,G)|A(2,S), 0),
+ EX_ID ( "isSubnode", FUNCTION, F_issubnode, I|A(1,G)|A(2,V), 0),
+ EX_ID ( "indegreeOf", FUNCTION, F_indegree, I|A(1,G)|A(2,V), 0),
+ EX_ID ( "outdegreeOf", FUNCTION, F_outdegree, I|A(1,G)|A(2,V), 0),
+ EX_ID ( "degreeOf", FUNCTION, F_degree, I|A(1,G)|A(2,V), 0),
+ EX_ID ( "isIn", FUNCTION, F_isin, I|A(1,G)|A(2,O), 0),
+ EX_ID ( "edge", FUNCTION, F_edge, E|A(1,V)|A(2,V)|A(3,S), 0),
+ EX_ID ( "edge_sg", FUNCTION, F_edgesg, E|A(1,G)|A(2,V)|A(3,V)|A(4,S), 0),
+ EX_ID ( "subedge", FUNCTION, F_addedge, E|A(1,G)|A(2,E), 0),
+ EX_ID ( "fstout", FUNCTION, F_fstout, E|A(1,V), 0),
+ EX_ID ( "nxtout", FUNCTION, F_nxtout, E|A(1,E), 0),
+ EX_ID ( "fstin", FUNCTION, F_fstin, E|A(1,V), 0),
+ EX_ID ( "nxtin", FUNCTION, F_nxtin, E|A(1,E), 0),
+ EX_ID ( "fstedge", FUNCTION, F_fstedge, E|A(1,V), 0),
+ EX_ID ( "nxtedge", FUNCTION, F_nxtedge, E|A(1,E)|A(2,V), 0),
+ EX_ID ( "fstout_sg", FUNCTION, F_fstoutsg, E|A(1,G)|A(2,V), 0),
+ EX_ID ( "nxtout_sg", FUNCTION, F_nxtoutsg, E|A(1,G)|A(2,E), 0),
+ EX_ID ( "fstin_sg", FUNCTION, F_fstinsg, E|A(1,G)|A(2,V), 0),
+ EX_ID ( "nxtin_sg", FUNCTION, F_nxtinsg, E|A(1,G)|A(2,E), 0),
+ EX_ID ( "fstedge_sg", FUNCTION, F_fstedgesg, E|A(1,G)|A(2,V), 0),
+ EX_ID ( "nxtedge_sg", FUNCTION, F_nxtedgesg, E|A(1,G)|A(2,E)|A(3,V), 0),
+ EX_ID ( "compOf", FUNCTION, F_compof, G|A(1,G)|A(2,V), 0),
+ EX_ID ( "kindOf", FUNCTION, F_kindof, S|A(1,O), 0),
+ EX_ID ( "index", FUNCTION, F_index, I|A(1,S)|A(2,S), 0),
+ EX_ID ( "rindex", FUNCTION, F_rindex, I|A(1,S)|A(2,S), 0),
+ EX_ID ( "isEdge", FUNCTION, F_isedge, E|A(1,V)|A(2,V)|A(3,S), 0),
+ EX_ID ( "isEdge_sg", FUNCTION, F_isedgesg, E|A(1,G)|A(2,V)|A(3,V)|A(4,S), 0),
+ EX_ID ( "isSubedge", FUNCTION, F_issubedge, I|A(1,G)|A(2,E), 0),
+ EX_ID ( "length", FUNCTION, F_length, I|A(1,S), 0),
+ EX_ID ( "match", FUNCTION, F_match, I|A(1,S)|A(2,S), 0),
+ EX_ID ( "write", FUNCTION, F_write, I|A(1,G), 0),
+ EX_ID ( "writeG", FUNCTION, F_writeg, I|A(1,G)|A(2,S), 0),
+ EX_ID ( "readG", FUNCTION, F_readg, G|A(1,S), 0),
+ EX_ID ( "fwriteG", FUNCTION, F_fwriteg, I|A(1,G)|A(2,I), 0),
+ EX_ID ( "freadG", FUNCTION, F_freadg, G|A(1,I), 0),
+ EX_ID ( "openF", FUNCTION, F_openf, I|A(1,S)|A(2,S), 0),
+ EX_ID ( "closeF", FUNCTION, F_closef, I|A(1,I), 0),
+ EX_ID ( "readL", FUNCTION, F_readl, S|A(1,I), 0),
+ EX_ID ( "induce", FUNCTION, F_induce, I|A(1,G), 0),
+ EX_ID ( "isDirect", FUNCTION, F_isdirect, I|A(1,G), 0),
+ EX_ID ( "isStrict", FUNCTION, F_isstrict, I|A(1,G), 0),
+ EX_ID ( "delete", FUNCTION, F_delete, I|A(1,G)|A(2,O), 0),
+ EX_ID ( "clone", FUNCTION, F_clone, O|A(1,G)|A(2,O), 0),
+ EX_ID ( "copy", FUNCTION, F_copy, O|A(1,G)|A(2,O), 0),
+ EX_ID ( "copyA", FUNCTION, F_copya, I|A(1,O)|A(2,O), 0),
+ EX_ID ( "lock", FUNCTION, F_lock, I|A(1,G)|A(2,I), 0),
+ EX_ID ( "nNodes", FUNCTION, F_nnodes, I|A(1,G), 0),
+ EX_ID ( "nEdges", FUNCTION, F_nedges, I|A(1,G), 0),
+ EX_ID ( "sqrt", FUNCTION, F_sqrt, F|A(1,F), 0),
+ EX_ID ( "cos", FUNCTION, F_cos, F|A(1,F), 0),
+ EX_ID ( "sin", FUNCTION, F_sin, F|A(1,F), 0),
+ EX_ID ( "atan2", FUNCTION, F_atan2, F|A(1,F)|A(2,F), 0),
+ EX_ID ( "exp", FUNCTION, F_exp, F|A(1,F), 0),
+ EX_ID ( "pow", FUNCTION, F_pow, F|A(1,F)|A(2,F), 0),
+ EX_ID ( "log", FUNCTION, F_log, F|A(1,F), 0),
+ EX_ID ( "MIN", FUNCTION, F_min, F|A(1,F)|A(2,F), 0),
+ EX_ID ( "MAX", FUNCTION, F_max, F|A(1,F)|A(2,F), 0),
+ EX_ID ( "system", FUNCTION, F_sys, I|A(1,S), 0),
+ EX_ID ( "xOf", FUNCTION, F_xof, S|A(1,S), 0),
+ EX_ID ( "yOf", FUNCTION, F_yof, S|A(1,S), 0),
+ EX_ID ( "llOf", FUNCTION, F_llof, S|A(1,S), 0),
+ EX_ID ( "urOf", FUNCTION, F_urof, S|A(1,S), 0),
+ EX_ID ( "canon", FUNCTION, F_canon, S|A(1,S), 0),
+ EX_ID ( "aget", FUNCTION, F_get, S|A(1,O)|A(2,S), 0),
+ EX_ID ( "aset", FUNCTION, F_set, I|A(1,O)|A(2,S)|A(3,S), 0),
+ EX_ID ( "getDflt", FUNCTION, F_dget, S|A(1,G)|A(2,S)|A(3,S), 0),
+ EX_ID ( "setDflt", FUNCTION, F_dset, I|A(1,G)|A(2,S)|A(3,S)|A(4,S), 0),
+ EX_ID ( "hasAttr", FUNCTION, F_hasattr, I|A(1,O)|A(2,S), 0),
+ EX_ID ( "isAttr", FUNCTION, F_isattr, I|A(1,G)|A(2,S)|A(3,S), 0),
+ EX_ID ( "fstAttr", FUNCTION, F_fstattr, S|A(1,G)|A(2,S), 0),
+ EX_ID ( "nxtAttr", FUNCTION, F_nxtattr, S|A(1,G)|A(2,S)|A(3,S), 0),
+ EX_ID ( "TV_flat", CONSTANT, C_flat, T_tvtyp, 0),
+ EX_ID ( "TV_ne", CONSTANT, C_ne, T_tvtyp, 0),
+ EX_ID ( "TV_en", CONSTANT, C_en, T_tvtyp, 0),
+ EX_ID ( "TV_bfs", CONSTANT, C_bfs, T_tvtyp, 0),
+ EX_ID ( "TV_dfs", CONSTANT, C_dfs, T_tvtyp, 0),
+ EX_ID ( "TV_fwd", CONSTANT, C_fwd, T_tvtyp, 0),
+ EX_ID ( "TV_rev", CONSTANT, C_rev, T_tvtyp, 0),
+ EX_ID ( "TV_postdfs", CONSTANT, C_postdfs, T_tvtyp, 0),
+ EX_ID ( "TV_postfwd", CONSTANT, C_postfwd, T_tvtyp, 0),
+ EX_ID ( "TV_postrev", CONSTANT, C_postrev, T_tvtyp, 0),
+ EX_ID ( "TV_prepostdfs", CONSTANT, C_prepostdfs, T_tvtyp, 0),
+ EX_ID ( "TV_prepostfwd", CONSTANT, C_prepostfwd, T_tvtyp, 0),
+ EX_ID ( "TV_prepostrev", CONSTANT, C_prepostrev, T_tvtyp, 0),
+ EX_ID ( "NULL", CONSTANT, C_null, T_obj, 0),
+ EX_ID ( {0}, 0, 0, 0, 0)
+};
+
+static char* typenames[] = {
+ "node_t",
+ "edge_t",
+ "graph_t",
+ "obj_t",
+ "tvtype_t",
+};
+
+typedef unsigned short tctype;
+
+static tctype tchk[][2] = {
+ { 0, 0 },
+ { 0, YALL },
+ { 0, Y(G) },
+ { 0, Y(G) },
+ { 0, Y(G) },
+ { 0, Y(S) },
+ { 0, Y(S) },
+ { 0, Y(V) },
+ { 0, Y(TV) },
+ { 0, Y(I) },
+ { Y(V), Y(I) },
+ { Y(E), Y(V) },
+ { Y(E), Y(V) },
+ { YALL, Y(S) },
+ { Y(V), Y(I) },
+ { Y(V), Y(I) },
+ { YALL, Y(G) },
+ { Y(G), Y(G) },
+ { Y(G), Y(I) },
+ { Y(G), Y(I) },
+ { Y(G), Y(I) },
+ { Y(G), Y(I) },
+};
+
+#endif
return ((TV_flat <= c) && (c <= TV_prepostrev));
}
-void initGPRState(Gpr_t * state, Vmalloc_t * vm, gpr_info * info)
+void initGPRState(Gpr_t * state, Vmalloc_t * vm)
{
state->tgtname = vmstrdup(vm, "gvpr_result");
- state->tvt = TV_flat;
- state->tvroot = 0;
- state->outFile = info->outFile;
- state->argc = info->argc;
- state->argv = info->argv;
}
-Gpr_t *openGPRState()
+Gpr_t *openGPRState(gpr_info* info)
{
Gpr_t *state;
- if (!(state = newof(0, Gpr_t, 1, 0)))
- error(ERROR_FATAL, "Could not create gvpr state: out of memory");
+ if (!(state = newof(0, Gpr_t, 1, 0))) {
+ error(ERROR_ERROR, "Could not create gvpr state: out of memory");
+ return state;
+ }
+
+ if (!(state->tmp = sfstropen())) {
+ error(ERROR_ERROR, "Could not create state tmpfile");
+ free (state);
+ return 0;
+ }
- if (!(state->tmp = sfstropen()))
- error(ERROR_FATAL, "Could not create state");
+ state->tvt = TV_flat;
+ state->tvroot = 0;
+ state->outFile = info->outFile;
+ state->argc = info->argc;
+ state->argv = info->argv;
+ state->errf = info->errf;
+ state->flags = info->flags;
return state;
}
+void closeGPRState(Gpr_t* state)
+{
+ if (!state) return;
+ if (state->tmp)
+ sfclose (state->tmp);
+ free (state->dp);
+ free (state);
+}
+
#ifdef WIN32_DLL
int pathisrelative (char* path)
{
#include "cgraph.h"
#include "ast.h"
#include "vmalloc.h"
+#include "expr.h"
typedef enum { TV_flat, TV_ne, TV_en,
TV_bfs,
Agraph_t *outgraph;
Agobj_t *curobj;
Sfio_t *tmp;
+ Exdisc_t *dp;
+ Exerror_f errf;
+ Exexit_f exitf;
char *tgtname;
char *infname;
Sfio_t *outFile;
int name_used;
int argc;
char **argv;
+ int flags;
} Gpr_t;
typedef struct {
Sfio_t *outFile;
int argc;
char **argv;
+ Exerror_f errf;
+ Exexit_f exitf;
+ int flags;
} gpr_info;
- extern Gpr_t *openGPRState(void);
- extern void initGPRState(Gpr_t *, Vmalloc_t *, gpr_info *);
+ extern Gpr_t *openGPRState(gpr_info*);
+ extern void closeGPRState(Gpr_t* state);
+ extern void initGPRState(Gpr_t *, Vmalloc_t *);
extern int validTVT(int);
#ifdef WIN32_DLL
#include "ingraphs.h"
#include "compile.h"
#include "queue.h"
+#include "gvpr.h"
+#include "actions.h"
#include "sfstr.h"
#include <error.h>
#include <string.h>
#include <ctype.h>
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
-#include "compat_getopt.h"
-#endif
-
-char *Info[] = {
- "gvpr", /* Program */
- VERSION, /* Version */
- BUILDDATE /* Build Date */
-};
+#include <setjmp.h>
#define DFLT_GPRPATH "."
+#define GV_USE_JUMP 4
+
+static char *Info[] = {
+ "gvpr", /* Program */
+ VERSION, /* Version */
+ BUILDDATE /* Build Date */
+};
+
static const char *usage =
- ": gvpr [-o <ofile>] [-a <args>] ([-f <prog>] | 'prog') [files]\n\
+ " [-o <ofile>] [-a <args>] ([-f <prog>] | 'prog') [files]\n\
-c - use source graph for output\n\
-f <pfile> - find program in file <pfile>\n\
-i - create node induced subgraph\n\
-? - print usage info\n\
If no files are specified, stdin is used\n";
-struct {
- char *cmdName;
+typedef struct {
+ char *cmdName; /* command name */
Sfio_t *outFile; /* output stream; stdout default */
- char *program;
+ char *program; /* program source */
int useFile; /* true if program comes from a file */
int compflags;
char **inFiles;
int argc;
char **argv;
+ int state; /* > 0 : continue; <= 0 finish */
} options;
static Sfio_t *openOut(char *name)
outs = sfopen(0, name, "w");
if (outs == 0) {
- error(ERROR_FATAL, "could not open %s for writing", name);
+ error(ERROR_ERROR, "could not open %s for writing", name);
}
return outs;
}
* NB. There must be white space between tokens. Otherwise, they
* are concatenated.
*/
-static char*
-gettok (char** sp)
+static char *gettok(char **sp)
{
- char* s = *sp;
- char* ws = s;
- char* rs = s;
- char c;
- char q = '\0'; /* if non-0, in quote mode with quote char q */
-
- while (isspace(*rs)) rs++;
- if ((c = *rs) == '\0') return NULL;
+ char *s = *sp;
+ char *ws = s;
+ char *rs = s;
+ char c;
+ char q = '\0'; /* if non-0, in quote mode with quote char q */
+
+ while (isspace(*rs))
+ rs++;
+ if ((c = *rs) == '\0')
+ return NULL;
while ((c = *rs)) {
- if (q && (q == c)) { /* end quote */
+ if (q && (q == c)) { /* end quote */
q = '\0';
- }
- else if (!q && ((c == '"') || (c == '\''))) {
+ } else if (!q && ((c == '"') || (c == '\''))) {
q = c;
- }
- else if (c == '\\') {
+ } else if (c == '\\') {
rs++;
c = *rs;
- if (c) *ws++ = c;
+ if (c)
+ *ws++ = c;
else {
- error(ERROR_WARNING,
- "backslash in argument followed by no character - ignored");
+ error(ERROR_WARNING,
+ "backslash in argument followed by no character - ignored");
rs--;
}
- }
- else if (q || !isspace(c))
+ } else if (q || !isspace(c))
*ws++ = c;
- else break;
- rs++;
+ else
+ break;
+ rs++;
}
- if (*rs) rs++;
+ if (*rs)
+ rs++;
else if (q)
error(ERROR_WARNING, "no closing quote for argument %s", s);
*sp = rs;
argc = oldcnt + cnt;
av = oldof(*argv, char *, argc, 0);
for (i = 0; i < cnt; i++)
- av[oldcnt+i] = strdup(args[i]);
+ av[oldcnt + i] = strdup(args[i]);
*argv = av;
}
return argc;
* Translate -f arg parameter into a pathname.
* If arg contains '/', return arg.
* Else search directories in GPRPATH for arg.
+ * Return NULL on error.
*/
static char *resolve(char *arg)
{
size_t sz;
#ifdef WIN32_DLL
- if (!pathisrelative (arg))
+ if (!pathisrelative(arg))
#else
if (strchr(arg, '/'))
#endif
- return arg;
+ return strdup(arg);
path = getenv("GPRPATH");
if (!path)
path = DFLT_GPRPATH;
- if (!(fp = sfstropen()))
- error(ERROR_FATAL, "Could not open buffer");
+ if (!(fp = sfstropen())) {
+ error(ERROR_ERROR, "Could not open buffer");
+ return 0;
+ }
while (*path && !fname) {
if (*path == LISTSEP) { /* skip colons */
}
if (!fname)
- error(ERROR_FATAL, "Could not find file \"%s\" in GPRPATH", arg);
+ error(ERROR_ERROR, "Could not find file \"%s\" in GPRPATH", arg);
sfclose(fp);
return fname;
}
-/* scanArgs:
- * Parse command line options.
+static char*
+getOptarg (int c, char** argp, int* argip, int argc, char** argv)
+{
+ char* rv;
+ char* arg = *argp;
+ int argi = *argip;
+
+ if (*arg) {
+ rv = arg;
+ while (*arg) arg++;
+ *argp = arg;
+ }
+ else if (argi < argc) {
+ rv = argv[argi++];
+ *argip = argi;
+ }
+ else {
+ rv = NULL;
+ error(ERROR_WARNING, "missing argument for option -%c", c);
+ }
+ return rv;
+}
+
+/* doFlags:
+ * Process a command-line argument starting with a '-'.
+ * argi is the index of the next available item in argv[].
+ * argc has its usual meaning.
+ *
+ * return > 0 given next argi value
+ * = 0 for exit with 0
+ * < 0 for error
*/
-static void scanArgs(int argc, char **argv)
+static int
+doFlags(char* arg, int argi, int argc, char** argv, options* opts)
{
int c;
- char *outname = 0;
-
- options.cmdName = argv[0];
- options.outFile = 0;
- options.useFile = 0;
- options.argv = 0;
- options.argc = 0;
-#ifdef GVDLL
- setErrorId (options.cmdName);
-#else
- error_info.id = options.cmdName;
-#endif
- while ((c = getopt(argc, argv, ":q?Vcia:f:o:")) != -1) {
+ while ((c = *arg++)) {
switch (c) {
case 'c':
- options.compflags |= SRCOUT;
+ opts->compflags |= SRCOUT;
+ break;
+ case 'C':
+ opts->compflags |= (SRCOUT|CLONE);
break;
case 'f':
- options.useFile = 1;
- options.program = resolve(optarg);
+ if ((optarg = getOptarg(c, &arg, &argi, argc, argv)) && (opts->program = resolve(optarg))) {
+ opts->useFile = 1;
+ }
+ else return -1;
break;
case 'i':
- options.compflags |= INDUCE;
+ opts->compflags |= INDUCE;
break;
case 'a':
- options.argc = parseArgs(optarg, options.argc, &options.argv);
+ if ((optarg = getOptarg(c, &arg, &argi, argc, argv))) {
+ opts->argc = parseArgs(optarg, opts->argc, &(opts->argv));
+ }
+ else return -1;
break;
case 'o':
- outname = optarg;
+ if (!(optarg = getOptarg(c, &arg, &argi, argc, argv)) && !(opts->outFile = openOut(optarg)))
+ return -1;
break;
case 'q':
- setTraceLevel (ERROR_ERROR);
+ setTraceLevel (ERROR_ERROR); /* Don't emit warning messages */
break;
case 'V':
- fprintf(stderr, "%s version %s (%s)\n",
+ sfprintf(sfstderr, "%s version %s (%s)\n",
Info[0], Info[1], Info[2]);
- exit(0);
+ return 0;
break;
case '?':
- if (optopt == '?') {
- error(ERROR_USAGE, "%s", usage);
- exit(0);
- } else {
- error(ERROR_ERROR, "option -%c unrecognized", optopt);
- }
+ error(ERROR_USAGE|ERROR_WARNING, "%s", usage);
+ return 0;
break;
- case ':':
- error(ERROR_ERROR, "missing argument for option -%c", optopt);
+ default :
+ error(ERROR_WARNING, "option -%c unrecognized", c);
break;
}
}
- argv += optind;
- argc -= optind;
+ return argi;
+}
+
+static void
+freeOpts (options* opts)
+{
+ int i;
+ if (!opts) return;
+ if (opts->outFile != sfstdout)
+ sfclose (opts->outFile);
+ free (opts->inFiles);
+ if (opts->useFile)
+ free (opts->program);
+ if (opts->argc) {
+ for (i = 0; i < opts->argc; i++)
+ free (opts->argv[i]);
+ free (opts->argv);
+ }
+ free (opts);
+}
+
+/* scanArgs:
+ * Parse command line options.
+ */
+static options* scanArgs(int argc, char **argv, gvpropts* uopts)
+{
+ int i, nfiles;
+ char** input_filenames;
+ char* arg;
+ options* opts = newof(0,options,1,0);
+
+ opts->cmdName = argv[0];
+ opts->state = 1;
+ setErrorId (opts->cmdName);
+
+ /* estimate number of file names */
+ nfiles = 0;
+ for (i = 1; i < argc; i++)
+ if (argv[i] && argv[i][0] != '-')
+ nfiles++;
+ input_filenames = newof(0,char*,nfiles + 1,0);
+
+ /* loop over arguments */
+ nfiles = 0;
+ for (i = 1; i < argc; ) {
+ arg = argv[i++];
+ if (*arg == '-') {
+ i = doFlags (arg+1, i, argc, argv, opts);
+ if (i <= 0) {
+ opts->state = i;
+ goto opts_done;
+ }
+ } else if (arg)
+ input_filenames[nfiles++] = arg;
+ }
/* Handle additional semantics */
- if (options.useFile == 0) {
- if (argc == 0) {
- error(ERROR_ERROR, "No program supplied via argument or -f option");
-#ifdef GVDLL
- setErrorErrors (1);
-#else
- error_info.errors = 1;
-#endif
+ if (opts->useFile == 0) {
+ if (nfiles == 0) {
+ error(ERROR_ERROR,
+ "No program supplied via argument or -f option");
+ opts->state = -1;
} else {
- options.program = *argv++;
- argc--;
+ opts->program = input_filenames[0];
+ for (i = 1; i <= nfiles; i++)
+ input_filenames[i-1] = input_filenames[i];
+ nfiles--;
}
}
- if (argc == 0)
- options.inFiles = 0;
- else
- options.inFiles = argv;
- if (outname)
- options.outFile = openOut(outname);
+ if (nfiles == 0) {
+ opts->inFiles = 0;
+ free (input_filenames);
+ input_filenames = 0;
+ }
else
- options.outFile = sfstdout;
+ opts->inFiles = input_filenames;
-#ifdef GVDLL
- if (getErrorErrors ())
-#else
- if (error_info.errors)
-#endif
- error(ERROR_USAGE | 4, "%s", usage);
+ if (!(opts->outFile))
+ opts->outFile = sfstdout;
+
+ opts_done:
+ if (opts->state <= 0) {
+ if (opts->state < 0)
+ error(ERROR_USAGE|ERROR_ERROR, "%s", usage);
+ free (input_filenames);
+ }
+
+ return opts;
}
static void evalEdge(Gpr_t * state, comp_prog * xprog, Agedge_t * e)
#define PUSH(x) (((x)->iu.integer)|=2)
#define POP(x) (((x)->iu.integer)&=(~2))
-typedef Agedge_t *(*fstedgefn_t) (Agraph_t*, Agnode_t *);
-typedef Agedge_t *(*nxttedgefn_t) (Agraph_t*, Agedge_t *, Agnode_t *);
+typedef Agedge_t *(*fstedgefn_t) (Agraph_t *, Agnode_t *);
+typedef Agedge_t *(*nxttedgefn_t) (Agraph_t *, Agedge_t *, Agnode_t *);
#define PRE_VISIT 1
#define POST_VISIT 2
unsigned char visit;
} trav_fns;
-static trav_fns DFSfns = { agfstedge, agnxtedge, 1, 0};
-static trav_fns FWDfns = { agfstout, (nxttedgefn_t) agnxtout, 0, 0};
-static trav_fns REVfns = { agfstin, (nxttedgefn_t) agnxtin, 0, 0};
+static trav_fns DFSfns = { agfstedge, agnxtedge, 1, 0 };
+static trav_fns FWDfns = { agfstout, (nxttedgefn_t) agnxtout, 0, 0 };
+static trav_fns REVfns = { agfstin, (nxttedgefn_t) agnxtin, 0, 0 };
static void travBFS(Gpr_t * state, comp_prog * xprog)
{
ndata *nd;
Agnode_t *n;
Agedge_t *cure;
- Agraph_t* g = state->curgraph;
+ Agraph_t *g = state->curgraph;
q = mkQueue();
nodes.oldroot = 0;
if (MARKED(nd))
continue;
PUSH(nd);
- push (q,n);
+ push(q, n);
while ((n = pull(q))) {
nd = nData(n);
MARK(nd);
- POP(nd);
+ POP(nd);
evalNode(state, xprog, n);
- for (cure = agfstedge(g, n); cure; cure = agnxtedge(g, cure, n)) {
+ for (cure = agfstedge(g, n); cure;
+ cure = agnxtedge(g, cure, n)) {
nd = nData(cure->node);
- if (MARKED(nd)) continue;
+ if (MARKED(nd))
+ continue;
evalEdge(state, xprog, cure);
if (!ONSTACK(nd)) {
push(q, cure->node);
}
}
}
- freeQ (q);
+ freeQ(q);
}
static void travDFS(Gpr_t * state, comp_prog * xprog, trav_fns * fns)
else
cure = fns->fstedge(state->curgraph, curn);
if (cure) {
- if (entry == agopp(cure)) /* skip edge used to get here */
+ if (entry == agopp(cure)) /* skip edge used to get here */
continue;
nd = nData(cure->node);
if (MARKED(nd)) {
- /* For undirected DFS, visit an edge only if its head
- * is on the stack, to avoid visiting it twice.
- * This is no problem in directed DFS.
- */
+ /* For undirected DFS, visit an edge only if its head
+ * is on the stack, to avoid visiting it twice.
+ * This is no problem in directed DFS.
+ */
if (fns->undirected) {
- if (ONSTACK(nd)) evalEdge(state, xprog, cure);
- }
- else
+ if (ONSTACK(nd))
+ evalEdge(state, xprog, cure);
+ } else
evalEdge(state, xprog, cure);
} else {
evalEdge(state, xprog, cure);
}
}
}
- freeQ (stk);
+ freeQ(stk);
}
static void travNodes(Gpr_t * state, comp_prog * xprog)
{
Agnode_t *n;
- Agraph_t* g = state->curgraph;
+ Agraph_t *g = state->curgraph;
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
evalNode(state, xprog, n);
}
{
Agnode_t *n;
Agedge_t *e;
- Agraph_t* g = state->curgraph;
+ Agraph_t *g = state->curgraph;
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
evalEdge(state, xprog, e);
{
Agnode_t *n;
Agedge_t *e;
- Agraph_t* g = state->curgraph;
+ Agraph_t *g = state->curgraph;
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
evalNode(state, xprog, n);
if (xprog->n_estmts > 0) {
}
}
+/* addOutputGraph:
+ * Append output graph to option struct.
+ * We know uopts and state->outgraph are non-NULL.
+ */
+static void
+addOutputGraph (Gpr_t* state, gvpropts* uopts)
+{
+ Agraph_t* g = state->outgraph;
+
+ if ((agroot(g) == state->curgraph) && !uopts->ingraphs)
+ g = (Agraph_t*)clone (0, (Agobj_t *)g);
+
+ uopts->n_outgraphs++;
+ uopts->outgraphs = oldof(uopts->outgraphs,Agraph_t*,uopts->n_outgraphs,0);
+ uopts->outgraphs[uopts->n_outgraphs-1] = g;
+}
+
static void chkClose(Agraph_t * g)
{
gdata *data;
return sfclose((Sfio_t *) fp);
}
-#ifdef GVDLL
static ingdisc ingDisc = { ing_open, ing_read, ing_close, 0 };
-#else
-static ingdisc ingDisc = { ing_open, ing_read, ing_close, &_Sfstdin };
-#endif
-int main(int argc, char *argv[])
+static void
+setDisc (Sfio_t* sp, Sfdisc_t* dp, gvprwr fn)
{
- parse_prog *prog;
+ dp->readf = 0;
+ dp->writef = (Sfwrite_f)fn;
+ dp->seekf = 0;
+ dp->exceptf = 0;
+ dp->disc = 0;
+ dp = sfdisc (sp, dp);
+}
+
+static jmp_buf jbuf;
+
+/* gvexitf:
+ * Only used if GV_USE_EXIT not set during exeval.
+ * This implies setjmp/longjmp set up.
+ */
+static void
+gvexitf (Expr_t *handle, Exdisc_t *discipline, int v)
+{
+ longjmp (jbuf, v);
+}
+
+static int
+gverrorf (Expr_t *handle, Exdisc_t *discipline, int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv((discipline
+ && handle) ? *((char **) handle) : (char *) handle, level, ap);
+ va_end(ap);
+
+ if (level >= ERROR_ERROR) {
+ Gpr_t *state = (Gpr_t*)(discipline->user);
+ if (state->flags & GV_USE_EXIT)
+ exit(1);
+ else if (state->flags & GV_USE_JUMP)
+ longjmp (jbuf, 1);
+ }
+
+ return 0;
+}
+
+/* gvpr:
+ * main loop for gvpr.
+ * Return 0 on success; non-zero on error.
+ *
+ * FIX:
+ * - close non-source/non-output graphs
+ */
+int gvpr (int argc, char *argv[], gvpropts * uopts)
+{
+ Sfdisc_t errdisc;
+ Sfdisc_t outdisc;
+ parse_prog *prog = 0;
ingraph_state *ing;
- comp_prog *xprog;
- Gpr_t *state;
+ comp_prog *xprog = 0;
+ Gpr_t *state = 0;
gpr_info info;
+ int rv = 0;
+ options* opts = 0;
+ int incoreGraphs;
+
+ setErrorErrors (0);
+ ingDisc.dflt = sfstdin;
+ if (uopts) {
+ if (uopts->out) setDisc (sfstdout, &outdisc, uopts->out);
+ if (uopts->err) setDisc (sfstderr, &errdisc, uopts->err);
+ }
-#ifdef GVDLL
- ingDisc.dflt = &_Sfstdin;
-#endif
- scanArgs(argc, argv);
+ opts = scanArgs(argc, argv, uopts);
+ if (opts->state <= 0) {
+ rv = opts->state;
+ goto finish;
+ }
+
+ prog = parseProg(opts->program, opts->useFile);
+ if (!prog) {
+ rv = 1;
+ goto finish;
+ }
+ info.outFile = opts->outFile;
+ info.argc = opts->argc;
+ info.argv = opts->argv;
+ info.errf = (Exerror_f)gverrorf;
+ if (uopts)
+ info.flags = uopts->flags;
+ else
+ info.flags = 0;
+ if ((uopts->flags & GV_USE_EXIT))
+ info.exitf = 0;
+ else
+ info.exitf = gvexitf;
+ state = openGPRState(&info);
+ if (!state) {
+ rv = 1;
+ goto finish;
+ }
+ xprog = compileProg(prog, state, opts->compflags);
+ if (!xprog) {
+ rv = 1;
+ goto finish;
+ }
+
+ initGPRState(state, xprog->prog->vm);
+
+ if ((uopts->flags & GV_USE_OUTGRAPH)) {
+ uopts->outgraphs = 0;
+ uopts->n_outgraphs = 0;
+ }
- prog = parseProg(options.program, options.useFile);
- state = openGPRState();
- xprog = compileProg(prog, state, options.compflags);
- info.outFile = options.outFile;
- info.argc = options.argc;
- info.argv = options.argv;
- initGPRState(state, xprog->prog->vm, &info);
+ if (!(uopts->flags & GV_USE_EXIT)) {
+ state->flags |= GV_USE_JUMP;
+ if ((rv = setjmp (jbuf))) {
+ goto finish;
+ }
+ }
+
+ if (uopts && uopts->ingraphs)
+ incoreGraphs = 1;
+ else
+ incoreGraphs = 0;
/* do begin */
if (xprog->begin_stmt)
/* if program is not null */
if (usesGraph(xprog)) {
- ing = newIng(0, options.inFiles, &ingDisc);
+ if (uopts && uopts->ingraphs)
+ ing = newIngGraphs(0, uopts->ingraphs, &ingDisc);
+ else
+ ing = newIng(0, opts->inFiles, &ingDisc);
+
while ((state->curgraph = nextGraph(ing))) {
state->infname = fileName(ing);
+
/* begin graph */
+ if (incoreGraphs && (opts->compflags & CLONE))
+ state->curgraph = clone (0, (Agobj_t*)(state->curgraph));
state->curobj = (Agobj_t *) state->curgraph;
state->tvroot = 0;
if (xprog->begg_stmt)
agdelete(state->curgraph, state->target);
/* output graph, if necessary
- * For this, the outgraph must be defined, and either
- * be non-empty or the -c option was used.
- */
- if (state->outgraph &&
- (agnnodes(state->outgraph) || (options.compflags & SRCOUT)))
- agwrite(state->outgraph, options.outFile);
-
- chkClose(state->curgraph);
+ * For this, the outgraph must be defined, and either
+ * be non-empty or the -c option was used.
+ */
+ if (state->outgraph && (agnnodes(state->outgraph)
+ || (opts->compflags & SRCOUT))) {
+ if (uopts && (uopts->flags & GV_USE_OUTGRAPH))
+ addOutputGraph (state, uopts);
+ else
+ agwrite(state->outgraph, opts->outFile);
+ }
+
+ if (!incoreGraphs)
+ chkClose(state->curgraph);
state->target = 0;
state->outgraph = 0;
}
}
- /* do end */
+ /* do end */
state->curgraph = 0;
state->curobj = 0;
if (xprog->end_stmt)
exeval(xprog->prog, xprog->end_stmt, state);
- exit(0);
+ finish:
+ /* free all allocated resources */
+ freeParseProg (prog);
+ freeCompileProg (xprog);
+ closeGPRState(state);
+ closeIngraph (ing);
+ freeOpts (opts);
+
+ if (uopts) {
+ if (uopts->out) sfdisc (sfstdout, 0);
+ if (uopts->err) sfdisc (sfstderr, 0);
+ }
+
+ return rv;
}
+
--- /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
+
+#ifndef GVPR_H
+#define GVPR_H
+
+#include "cgraph.h"
+
+ /* If set, gvpr calls exit() on errors */
+#define GV_USE_EXIT 1
+ /* If set, gvpr stores output graphs in gvpropts */
+#define GV_USE_OUTGRAPH 2
+
+typedef ssize_t (*gvprwr) (void*, const char *buf, size_t nbyte, void*);
+
+typedef struct {
+ Agraph_t** ingraphs; /* NULL-terminated array of input graphs */
+ int n_outgraphs; /* if GV_USE_OUTGRAPH set, output graphs */
+ Agraph_t** outgraphs;
+ gvprwr out; /* write function for stdout */
+ gvprwr err; /* write function for stderr */
+ int flags;
+} gvpropts;
+
+ extern int gvpr (int argc, char *argv[], gvpropts* opts);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE@
+
+Name: libgvpr
+Description: The GVPR library
+Version: @VERSION@
+Libs: -L${libdir} -lgvpr -lcgraph -lcdt
+Cflags: -I${includedir}
+
c = skipWS(str);
if (c < 0)
return Eof;
- if (!isalpha(c))
- error(ERROR_FATAL,
+ if (!isalpha(c)) {
+ error(ERROR_ERROR,
"expected keyword BEGIN/END/N/E...; found '%c', line %d", c,
lineno);
+ return Error;
+ }
kwLine = lineno;
parseID(str, c, buf, BSIZE);
break;
}
if (cs == Error)
- error(ERROR_FATAL, "unexpected keyword \"%s\", line %d", buf,
+ error(ERROR_ERROR, "unexpected keyword \"%s\", line %d", buf,
kwLine);
return cs;
}
* up to and including a terminating character ec
* that is not escaped with a back quote.
*/
-static void endString(Sfio_t * ins, Sfio_t * outs, char ec)
+static int endString(Sfio_t * ins, Sfio_t * outs, char ec)
{
int sline = lineno;
int c;
sfputc(outs, c);
c = sfgetc(ins);
}
- if (c < 0)
- error(ERROR_FATAL, "unclosed string, start line %d", sline);
+ if (c < 0) {
+ error(ERROR_ERROR, "unclosed string, start line %d", sline);
+ return c;
+ }
if (c == '\n')
lineno++;
sfputc(outs, (char) c);
}
sfputc(outs, c);
+ return 0;
}
/* endBracket:
sfputc(outs, (char) c);
} else if ((c == '\'') || (c == '"')) {
sfputc(outs, (char) c);
- endString(ins, outs, c);
+ if (endString(ins, outs, c)) return -1;
} else
sfputc(outs, (char) c);
}
}
startLine = lineno;
c = endBracket(str, buf, bc, ec);
- if (c < 0)
- error(ERROR_FATAL,
+ if (c < 0) {
+ if (!getErrorErrors())
+ error(ERROR_ERROR,
"unclosed bracket %c%c expression, start line %d", bc, ec,
startLine);
- return strdup(sfstruse(buf));
+ return 0;
+ }
+ else
+ return strdup(sfstruse(buf));
}
/* parseAction:
int *aline)
{
case_t kind;
+
Sfio_t *buf = sfstropen();
kind = parseKind(str);
case EndG:
*action = parseAction(str, buf);
*aline = startLine;
+ if (getErrorErrors ())
+ kind = Error;
break;
case Edge:
case Node:
*guard = parseGuard(str, buf);
*gline = startLine;
- *action = parseAction(str, buf);
- *aline = startLine;
+ if (!getErrorErrors ()) {
+ *action = parseAction(str, buf);
+ *aline = startLine;
+ }
+ if (getErrorErrors ())
+ kind = Error;
break;
case Eof:
case Error: /* to silence warnings */
error(ERROR_WARNING, "%s with no action, line %d - ignored",
caseStr(cs), kwLine);
else if (*ap)
- error(ERROR_FATAL, "additional %s section, line %d", caseStr(cs),
+ error(ERROR_ERROR, "additional %s section, line %d", caseStr(cs),
kwLine);
else {
*ap = action;
/* parseProg:
* Parses input into gpr sections.
- * Only returns if successful.
*/
parse_prog *parseProg(char *input, int isFile)
{
prog = newof(0, parse_prog, 1, 0);
if (!prog) {
- error(ERROR_FATAL, "parseProg: out of memory");
+ error(ERROR_ERROR, "parseProg: out of memory");
+ return 0;
}
if (isFile) {
str = sfopen(0, input, mode);
if (!str) {
if (isFile)
- error(ERROR_FATAL, "could not open %s for reading", input);
+ error(ERROR_ERROR, "could not open %s for reading", input);
else
- error(ERROR_FATAL, "parseProg : unable to create sfio stream");
+ error(ERROR_ERROR, "parseProg : unable to create sfio stream");
+ free (prog);
+ return 0;
}
more = 1;
edgelist = edgel;
break;
case Error: /* to silence warnings */
+ more = 0;
break;
}
}
sfclose(str);
+ if (getErrorErrors ()) {
+ freeParseProg (prog);
+ prog = 0;
+ }
+
return prog;
}
+
+static void
+freeCaseList (case_info* ip)
+{
+ case_info* nxt;
+ while (ip) {
+ nxt = ip->next;
+ free (ip->guard);
+ free (ip->action);
+ free (ip);
+ ip = nxt;
+ }
+}
+
+void
+freeParseProg (parse_prog * prog)
+{
+ if (!prog) return;
+ free (prog->begin_stmt);
+ free (prog->begg_stmt);
+ freeCaseList (prog->node_stmts);
+ freeCaseList (prog->edge_stmts);
+ free (prog->endg_stmt);
+ free (prog->end_stmt);
+ free (prog);
+}
+
extern parse_prog *parseProg(char *, int);
+ extern void freeParseProg (parse_prog *);
#endif
--- /dev/null
+#define UNDERLINE
+
+#include "trieFA.h"
+
+TrieState TrieStateTbl[70] = {
+ { -1, 0, 0x3b8620 },
+ { -1, 9, 0x440 },
+ { -1, 11, 0x100 },
+ { -1, 12, 0x80000 },
+ { -1, 13, 0x40 },
+ { -1, 14, 0x40 },
+ { Y(V), 15, 0x0 },
+ { -1, 15, 0x80000 },
+ { -1, 16, 0x40 },
+ { -1, 17, 0x10 },
+ { -1, 18, 0x200000 },
+ { -1, 19, 0x40 },
+ { -1, 20, 0x20 },
+ { Y(G), 21, 0x0 },
+ { -1, 21, 0x40 },
+ { -1, 22, 0x4 },
+ { -1, 23, 0x20 },
+ { Y(E), 24, 0x0 },
+ { -1, 24, 0x8000 },
+ { -1, 25, 0x20 },
+ { -1, 26, 0x40 },
+ { -1, 27, 0x100 },
+ { -1, 28, 0x80000 },
+ { -1, 29, 0x40 },
+ { -1, 30, 0x40 },
+ { Y(V), 31, 0x0 },
+ { -1, 31, 0x5 },
+ { -1, 33, 0x8040 },
+ { -1, 35, 0x20 },
+ { -1, 36, 0x100 },
+ { -1, 37, 0x40 },
+ { -1, 38, 0x100000 },
+ { Y(G), 39, 0x0 },
+ { -1, 39, 0x10000 },
+ { -1, 40, 0x20 },
+ { -1, 41, 0x40 },
+ { -1, 42, 0x100000 },
+ { Y(G), 43, 0x0 },
+ { -1, 43, 0x4000 },
+ { -1, 44, 0x40 },
+ { YALL, 45, 0x0 },
+ { -1, 45, 0x400000 },
+ { -1, 46, 0x200000 },
+ { -1, 47, 0x20 },
+ { -1, 48, 0x40 },
+ { -1, 49, 0x100 },
+ { -1, 50, 0x80000 },
+ { -1, 51, 0x40 },
+ { -1, 52, 0x40 },
+ { Y(V), 53, 0x0 },
+ { -1, 53, 0x4 },
+ { -1, 54, 0x80000 },
+ { -1, 55, 0x40 },
+ { -1, 56, 0x8000 },
+ { -1, 57, 0x200000 },
+ { Y(G), 58, 0x0 },
+ { -1, 58, 0x10000 },
+ { -1, 59, 0x10000 },
+ { -1, 60, 0x200000 },
+ { YALL, 61, 0x0 },
+ { -1, 61, 0x200000 },
+ { -1, 62, 0x80000 },
+ { -1, 63, 0x400 },
+ { -1, 64, 0x10 },
+ { -1, 65, 0x200000 },
+ { Y(G), 66, 0x0 },
+ { -1, 66, 0x4 },
+ { -1, 67, 0x400 },
+ { -1, 68, 0x2000 },
+ { Y(E), 69, 0x0 },
+};
+TrieTrans TrieTransTbl[69] = {
+ /* State 0 */ { 'd', 1 }, { 'h', 14 }, { 'i', 18 }, { 'n', 26 }, { 'o', 41 }, { 'p', 50 }, { 'r', 56 }, { 's', 60 }, { 't', 66 },
+ /* State 1 */ { 'e', 2 }, { 'i', 7 },
+ /* State 2 */ { 'g', 3 },
+ /* State 3 */ { 'r', 4 },
+ /* State 4 */ { 'e', 5 },
+ /* State 5 */ { 'e', 6 },
+ /* State 7 */ { 'r', 8 },
+ /* State 8 */ { 'e', 9 },
+ /* State 9 */ { 'c', 10 },
+ /* State 10 */ { 't', 11 },
+ /* State 11 */ { 'e', 12 },
+ /* State 12 */ { 'd', 13 },
+ /* State 14 */ { 'e', 15 },
+ /* State 15 */ { 'a', 16 },
+ /* State 16 */ { 'd', 17 },
+ /* State 18 */ { 'n', 19 },
+ /* State 19 */ { 'd', 20 },
+ /* State 20 */ { 'e', 21 },
+ /* State 21 */ { 'g', 22 },
+ /* State 22 */ { 'r', 23 },
+ /* State 23 */ { 'e', 24 },
+ /* State 24 */ { 'e', 25 },
+ /* State 26 */ { '_', 27 }, { 'a', 38 },
+ /* State 27 */ { 'e', 28 }, { 'n', 33 },
+ /* State 28 */ { 'd', 29 },
+ /* State 29 */ { 'g', 30 },
+ /* State 30 */ { 'e', 31 },
+ /* State 31 */ { 's', 32 },
+ /* State 33 */ { 'o', 34 },
+ /* State 34 */ { 'd', 35 },
+ /* State 35 */ { 'e', 36 },
+ /* State 36 */ { 's', 37 },
+ /* State 38 */ { 'm', 39 },
+ /* State 39 */ { 'e', 40 },
+ /* State 41 */ { 'u', 42 },
+ /* State 42 */ { 't', 43 },
+ /* State 43 */ { 'd', 44 },
+ /* State 44 */ { 'e', 45 },
+ /* State 45 */ { 'g', 46 },
+ /* State 46 */ { 'r', 47 },
+ /* State 47 */ { 'e', 48 },
+ /* State 48 */ { 'e', 49 },
+ /* State 50 */ { 'a', 51 },
+ /* State 51 */ { 'r', 52 },
+ /* State 52 */ { 'e', 53 },
+ /* State 53 */ { 'n', 54 },
+ /* State 54 */ { 't', 55 },
+ /* State 56 */ { 'o', 57 },
+ /* State 57 */ { 'o', 58 },
+ /* State 58 */ { 't', 59 },
+ /* State 60 */ { 't', 61 },
+ /* State 61 */ { 'r', 62 },
+ /* State 62 */ { 'i', 63 },
+ /* State 63 */ { 'c', 64 },
+ /* State 64 */ { 't', 65 },
+ /* State 66 */ { 'a', 67 },
+ /* State 67 */ { 'i', 68 },
+ /* State 68 */ { 'l', 69 },
+};
--- /dev/null
+/* File - trieFA.h
+ *
+ * This file contains code to be included in the scanner file using a
+ * generated trie-based FA.
+ */
+
+typedef struct { /* An entry in the FA state table */
+ short def; /* If this state is an accepting state then*/
+ /* this is the definition, otherwise -1. */
+ short trans_base; /* The base index into the transition table.*/
+ long mask; /* The transition mask. */
+}TrieState ;
+
+typedef struct { /* An entry in the FA transition table. */
+ short c; /* The transition character (lowercase).*/
+ short next_state; /* The next state. */
+}TrieTrans ;
+
+#ifdef UNDERLINE
+static long CharMask[28] = {
+ 0x0000001, 0x0000000, 0x0000004, 0x0000008,
+ 0x0000010, 0x0000020, 0x0000040, 0x0000080,
+ 0x0000100, 0x0000200, 0x0000400, 0x0000800,
+ 0x0001000, 0x0002000, 0x0004000, 0x0008000,
+ 0x0010000, 0x0020000, 0x0040000, 0x0080000,
+ 0x0100000, 0x0200000, 0x0400000, 0x0800000,
+ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
+};
+
+#define IN_MASK_RANGE(C) (islower(C) || ((C) == '_'))
+#define MASK_INDEX(C) ((C) - '_')
+
+#else
+static long CharMask[26] = {
+ 0x0000001, 0x0000002, 0x0000004, 0x0000008,
+ 0x0000010, 0x0000020, 0x0000040, 0x0000080,
+ 0x0000100, 0x0000200, 0x0000400, 0x0000800,
+ 0x0001000, 0x0002000, 0x0004000, 0x0008000,
+ 0x0010000, 0x0020000, 0x0040000, 0x0080000,
+ 0x0100000, 0x0200000, 0x0400000, 0x0800000,
+ 0x1000000, 0x2000000
+};
+
+#define IN_MASK_RANGE(C) islower(C)
+#define MASK_INDEX(C) ((C) - 'a')
+
+#endif
+
+static short TFA_State;
+
+/* TFA_Init:
+ *
+ * Initialize the trie FA.
+ */
+#define TFA_Init() TFA_State = 0
+
+/* TFA_Advance:
+ *
+ * Advance to the next state (or -1) on the lowercase letter c.
+ */
+#define TFA_Advance(C) { \
+ char c = C; \
+ if (TFA_State >= 0) { \
+ if (isupper(c)) \
+ c = tolower(c); \
+ else if (! IN_MASK_RANGE(c)) { \
+ TFA_State = -1; \
+ goto TFA_done; \
+ } \
+ if (TrieStateTbl[TFA_State].mask & CharMask[MASK_INDEX(c)]) { \
+ short i = TrieStateTbl[TFA_State].trans_base; \
+ while (TrieTransTbl[i].c != c) \
+ i++; \
+ TFA_State = TrieTransTbl[i].next_state; \
+ } \
+ else \
+ TFA_State = -1; \
+ } \
+ TFA_done:; \
+} /* end of TFA_Advance. */
+
+/* TFA_Definition:
+ *
+ * Return the definition (if any) associated with the current state.
+ */
+#define TFA_Definition() \
+ ((TFA_State < 0) ? -1 : TrieStateTbl[TFA_State].def)