41#define MIN(a, b) ((a) < (b) ? (a) : (b))
42#define MAX(a, b) ((a) > (b) ? (a) : (b))
49#define BITS_PER_BYTE 8
51static void *
int2ptr(
long long i) {
return (
void *)(intptr_t)i; }
53static long long ptr2int(
const void *p) {
return (
long long)(intptr_t)p; }
55static int iofread(
void *chan,
char *buf,
int bufsize) {
58 return (
int)
read(fileno(fp), buf, bufsize);
63static int ioflush(
void *chan) {
return fflush(chan); }
116 if (sscanf(pt,
"%lf,%lf,%lf,%lf", &x, &y, &u, &v) == 4) {
118 p = strchr(p + 1,
',');
120 size_t len = (size_t)(p - pt);
140 if (sscanf(pt,
"%lf,%lf", &x, &y) == 2) {
143 size_t len = (size_t)(p - pt);
172 if (sscanf(
ps,
"%lf,%lf", &p[0], &p[1]) == 2) {
179#if defined(DEBUG) && DEBUG > 1
180static char *symName(
Expr_t *ex,
int op) {
185 int bytes = vsnprintf(
NULL, 0,
"<unknown (%d)>", op);
187 fprintf(stderr,
"%s: vsnprintf failure\n", __func__);
192 char *
s =
vmalloc(ex->ve, (
size_t)bytes + 1);
196 snprintf(
s, (
size_t)bytes + 1,
"<unknown (%d)>", op);
217 while ((c = *args++)) {
269 exerror(
"null reference %s in expression %s.%s",
ref->symbol->name,
276 switch (
ref->symbol->index) {
294 if (!objp && !(objp = state->
curobj)) {
295 exerror(
"Current object $ not defined");
305 if (!objp && !(objp = state->
curobj)) {
306 exerror(
"Current object $ not defined");
313 exerror(
"tail of non-edge %p", objp);
316 exerror(
"%s : illegal reference",
ref->symbol->name);
329 unsigned char *p = name;
343 exerror(
"Cannot assign to pseudo-graph attribute %s", name);
347 exerror(
"Cannot assign to pseudo-node attribute %s", name);
351 exerror(
"Cannot assign to pseudo-edge attribute %s", name);
365 return agxset(objp, gsym, val);
397 if (sym->
lex ==
ID) {
398 switch (sym->
index) {
425 exerror(
"indegree of non-node");
433 exerror(
"outdegree of non-node");
450 exerror(
"x coordinate of non-node");
459 exerror(
"x coordinate of non-node");
467 exerror(
"parent of non-graph");
478 exerror(
"n_edges of non-graph");
486 exerror(
"n_nodes of non-graph");
494 exerror(
"directed of non-graph");
502 exerror(
"strict of non-graph");
517 "Using value of uninitialized %s attribute \"%s\" of \"%s\"",
531 if (n >= state->
argc) {
532 exerror(
"program references ARGV[%d] - undefined", n);
535 return (state->
argv[n]);
558 agattr(gp, kind, name, value);
579 exerror(
"Unknown kind \"%s\" passed to %s()", k, fn);
589 char *fn = (name ?
"nxtAttr" :
"fstAttr");
594 sym =
agattr(gp, kind, name, 0);
596 exerror(
"Third argument \"%s\" in nxtAttr() must be the name of an "
597 "existing attribute",
615 int kind =
toKind(k,
"getDflt");
618 sym =
agattr(gp, kind, name,
"");
646 switch (sym->
index) {
648 gp =
openG(args[0].
string,
xargs(args[1].
string));
804 objp =
int2ptr(args[1].integer);
827 objp =
int2ptr(args[0].integer);
829 exerror(
"NULL object passed to kindOf()");
1003 np =
int2ptr(args[0].integer);
1013 gp =
int2ptr(args[0].integer);
1014 np =
int2ptr(args[1].integer);
1026 ep =
int2ptr(args[0].integer);
1036 gp =
int2ptr(args[0].integer);
1037 ep =
int2ptr(args[1].integer);
1049 np =
int2ptr(args[0].integer);
1059 gp =
int2ptr(args[0].integer);
1060 np =
int2ptr(args[1].integer);
1072 ep =
int2ptr(args[0].integer);
1073 np =
int2ptr(args[1].integer);
1086 gp =
int2ptr(args[0].integer);
1087 ep =
int2ptr(args[1].integer);
1088 np =
int2ptr(args[2].integer);
1103 gp =
int2ptr(args[0].integer);
1104 objp =
int2ptr(args[1].integer);
1112 gp =
int2ptr(args[0].integer);
1113 objp =
int2ptr(args[1].integer);
1121 gp =
int2ptr(args[0].integer);
1123 gp =
cloneG(gp, args[1].
string);
1131 objp =
int2ptr(args[0].integer);
1132 objp1 =
int2ptr(args[1].integer);
1133 if (!(objp && objp1)) {
1140 gp =
int2ptr(args[0].integer);
1150 gp =
int2ptr(args[0].integer);
1158 gp =
int2ptr(args[0].integer);
1170 gp =
int2ptr(args[0].integer);
1191 gp =
int2ptr(args[0].integer);
1200 gp =
int2ptr(args[0].integer);
1209 gp =
int2ptr(args[0].integer);
1210 objp =
int2ptr(args[1].integer);
1220 }
else if (objp == state->
curobj) {
1227 gp =
int2ptr(args[0].integer);
1235 gp =
int2ptr(args[0].integer);
1244 gp =
int2ptr(args[0].integer);
1253 v.
integer = atoi(args[0].
string);
1259 v.
floating = sqrt(args[0].floating);
1262 v.
floating = cos(args[0].floating);
1265 v.
floating = sin(args[0].floating);
1268 v.
floating = atan2(args[0].floating, args[1].floating);
1271 v.
floating = exp(args[0].floating);
1274 v.
floating = pow(args[0].floating, args[1].floating);
1277 v.
floating = log(args[0].floating);
1280 v.
floating =
MIN(args[0].floating, args[1].floating);
1283 v.
floating =
MAX(args[0].floating, args[1].floating);
1286 v.
integer = system(args[0].
string);
1290 objp =
int2ptr(args[0].integer);
1291 char *name = args[1].
string;
1293 exerror(
"NULL object passed to aget()/hasAttr()");
1296 exerror(
"NULL name passed to aget()/hasAttr()");
1300 if (sym->
index == F_hasattr)
1307 "Using value of %s uninitialized attribute \"%s\" of \"%s\" "
1318 objp =
int2ptr(args[0].integer);
1323 char *name = args[1].
string;
1324 char *value = args[2].
string;
1328 }
else if (!value) {
1337 gp =
int2ptr(args[0].integer);
1339 char *kind = args[1].
string;
1340 char *name = args[2].
string;
1341 char *value = args[3].
string;
1345 }
else if (!value) {
1360 gp =
int2ptr(args[0].integer);
1362 char *kind = args[1].
string;
1370 exerror(
"NULL graph passed to fstAttr()");
1377 gp =
int2ptr(args[0].integer);
1379 char *kind = args[1].
string;
1380 char *name = args[2].
string;
1387 }
else if (sym->
index == F_isattr) {
1389 }
else if (sym->
index == F_nxtattr) {
1406 gp =
int2ptr(args[0].integer);
1418 v.
string =
colorx(pgm, args[0].
string, args[1].
string);
1421 if (args[0].
string) {
1423 v.
integer = strcmp(args[0].
string, args[1].
string);
1426 }
else if (args[1].
string)
1447 v.
integer = strlen(args[0].
string);
1456 const size_t m =
match(args[0].
string, args[1].
string);
1478 switch (sym->
index) {
1498 switch (sym->
index) {
1541 exerror(
"current object $ not defined as reference for %s",
1548 if (
lookup(pgm, objp, sym, &v)) {
1560#define MINTYPE (LAST_M + 1)
1578 objp =
deref(pgm, x,
ref, 0, state);
1585 }
else if (MINNAME <= sym->index && sym->
index <=
MAXNAME) {
1586 switch (sym->
index) {
1595 error(1,
"unexpected value %lld assigned to %s : ignored", iv,
1604 error(1,
"cannot set $tvroot, node %s not in $G : ignored",
1614 error(1,
"cannot set $tvnext, node %s not in $G : ignored",
1632 exerror(
"current object $ undefined in expression %s",
1645#define haveGraph (1 <= codePhase && codePhase <= 4)
1646#define haveTarget (2 <= codePhase && codePhase <= 4)
1647#define inWalk (2 <= codePhase && codePhase <= 3)
1662 switch (sym->
type) {
1686 exerror(
"unknown dynamic type %" PRIdMAX
" of symbol %s",
1693 switch (sym->
index) {
1699 exerror(
"keyword %s cannot be used in BEGIN/END statements",
1704 exerror(
"keyword %s cannot be used in BEGIN/BEG_G/END statements",
1717 exerror(
"undeclared, unmodified names like \"%s\" cannot be\nused in "
1718 "BEGIN and END statements",
1724 exerror(
"unexpected symbol in typeChk: name %s, lex %" PRIdMAX, sym->
name,
1725 (intmax_t)sym->
lex);
1732 if (!(dom & intype))
1766 switch (sym->
index) {
1843 if (l->
type == T_tvtyp) {
1847 if (r->
type != T_tvtyp)
1893 if (r && r->
type == T_tvtyp)
1951 if (!strcmp(sfx,
"flat")) {
1953 }
else if (!strcmp(sfx,
"ne")) {
1955 }
else if (!strcmp(sfx,
"en")) {
1957 }
else if (!strcmp(sfx,
"bfs")) {
1959 }
else if (!strcmp(sfx,
"dfs")) {
1961 }
else if (!strcmp(sfx,
"fwd")) {
1963 }
else if (!strcmp(sfx,
"rev")) {
1965 }
else if (!strcmp(sfx,
"postdfs")) {
1967 }
else if (!strcmp(sfx,
"postfwd")) {
1969 }
else if (!strcmp(sfx,
"postrev")) {
1971 }
else if (!strcmp(sfx,
"prepostdfs")) {
1973 }
else if (!strcmp(sfx,
"prepostfwd")) {
1975 }
else if (!strcmp(sfx,
"prepostrev")) {
1978 exerror(
"illegal string \"%s\" for type tvtype_t",
s);
1980 exerror(
"illegal string \"%s\" for type tvtype_t",
s);
2021 s =
"TV_prepostdfs";
2024 s =
"TV_prepostfwd";
2027 s =
"TV_prepostrev";
2030 exerror(
"Unexpected value %lld for type tvtype_t", v);
2049 if (x->
type == T_tvtyp) {
2081 if (
type == T_obj && x->
type <= T_obj)
2088 }
else if (x->
type == T_obj) {
2105 if (!objp ||
isedge(objp))
2111 if (x->
type == T_tvtyp) {
2124 exerror(
"Integer value %lld not legal for type tvtype_t",
2132 if (
type == T_tvtyp) {
2142 if (!arg && ret == 0)
2152 if (
type <= T_obj) {
2203 const char *lbl,
const char *sfx,
int kind) {
2208 FILE *sf = tmpfile();
2226 src =
"<command line>";
2257 for (
size_t i = 0; i < case_infos_size(&cases); i++) {
2258 case_info *sp = case_infos_at(&cases, i);
2278 if (!cs[i].action) {
2292 bool has_begin_g =
false;
2296 static const char PREFIX[] =
"_begin_g_";
2310 if (!case_infos_is_empty(&inp->
node_stmts)) {
2311 static const char PREFIX[] =
"_nd";
2325 if (!case_infos_is_empty(&inp->
edge_stmts)) {
2326 static const char PREFIX[] =
"_eg";
2356 return "\n$O = $G;\ninduce($O);\n";
2358 return "\n$O = $G;\n";
2361 return "\ninduce($O);\n";
2370 const char *endg_sfx =
NULL;
2371 bool uses_graph =
false;
2401 if (!parse_blocks_is_empty(&inp->
blocks)) {
2407 for (
size_t i = 0; i < parse_blocks_size(&inp->
blocks); bp++, i++) {
2456 for (
size_t i = 0; i < p->
n_blocks; i++) {
2530 root =
sameG(t, h,
"openEdge",
"tail and head nodes");
2534 if (!
sameG(g, root,
"openEdge",
"subgraph and nodes"))
2539 ep =
agedge(g, t, h, key, 1);
Agedge_t * isEdge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *key)
int indexOf(char *s1, char *s2)
Agraph_t * sameG(void *p1, void *p2, char *fn, char *msg)
Agraph_t * freadFile(Expr_t *ex, long long fd)
Agobj_t * cloneO(Agraph_t *g, Agobj_t *obj)
size_t match(char *str, char *pat)
int deleteObj(Agraph_t *g, Agobj_t *obj)
int writeFile(Agraph_t *g, char *f)
int fwriteFile(Expr_t *ex, Agraph_t *g, long long fd)
long rindexOf(char *s1, char *s2)
int sfioWrite(Agraph_t *g, FILE *fp)
char * toLower(Expr_t *pgm, char *src)
Agraph_t * cloneG(Agraph_t *g, char *name)
int lockGraph(Agraph_t *g, int v)
char * toHtml(Agraph_t *g, char *arg)
int compare(Agobj_t *l, Agobj_t *r)
Agobj_t * copy(Agraph_t *g, Agobj_t *obj)
Agraph_t * readFile(char *f)
Agraph_t * compOf(Agraph_t *g, Agnode_t *n)
char * colorx(Expr_t *ex, const char *incolor, char *fmt)
char * toUpper(Expr_t *pgm, char *src)
char * readLine(Expr_t *ex, long long fd)
int closeFile(Expr_t *ex, long long fd)
static void agxbfree(agxbuf *xb)
free any malloced resources
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
static int agxbputc(agxbuf *xb, char c)
add character to buffer
static char * agxbdisown(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void addNode(block_t *bp, Agnode_t *n)
abstract graph C library, Cgraph API
static char * deparse(Expr_t *ex, Exnode_t *n, agxbuf *xb)
static tctype typeChkExp(Exref_t *ref, Exid_t *sym)
static char * getDfltAttr(Agraph_t *gp, char *k, char *name)
Agedge_t * openEdge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *key)
comp_prog * compileProg(parse_prog *inp, Gpr_t *state, compflags_t flags)
static bool mkBlock(comp_block *bp, Expr_t *prog, char *src, parse_block *inp, size_t i)
static int lookup(Expr_t *pgm, Agobj_t *objp, Exid_t *sym, Extype_t *v)
static Agdesc_t xargs(char *args)
static tctype typeChk(tctype intype, Exid_t *sym)
static int strToTvtype(char *s)
static int iofread(void *chan, char *buf, int bufsize)
static case_stmt * mkStmts(Expr_t *prog, char *src, case_infos_t cases, const char *lbl)
Agraph_t * openG(char *name, Agdesc_t desc)
static char * getArg(int n, Gpr_t *state)
Agraph_t * openSubg(Agraph_t *g, char *name)
static char * tvtypeToStr(long long v)
static int stringOf(Expr_t *prog, Exnode_t *x, int arg)
static Agobj_t * deref(Expr_t *pgm, Exnode_t *x, Exref_t *ref, Agobj_t *objp, Gpr_t *state)
static int binary(Exnode_t *l, Exnode_t *ex, Exnode_t *r, int arg)
static char * bbOf(Expr_t *pgm, char *pt, bool getll)
void freeCompileProg(comp_prog *p)
static Exdisc_t * initDisc(Gpr_t *state)
static Extype_t getval(Expr_t *pgm, Exnode_t *node, Exid_t *sym, Exref_t *ref, void *env, int elt, Exdisc_t *disc)
Agnode_t * openNode(Agraph_t *g, char *name)
static char * typeName(long op)
Agraph_t * readG(FILE *fp)
static char * xyOf(Expr_t *pgm, char *pt, bool getx)
static char * kindToStr(int kind)
static char * nameOf(Expr_t *ex, Agobj_t *obj, agxbuf *tmps)
static int setDfltAttr(Agraph_t *gp, char *k, char *name, char *value)
static const char * doFlags(compflags_t flags)
static Extype_t refval(Expr_t *pgm, Exnode_t *node, Exid_t *sym, Exref_t *ref)
static long long ptr2int(const void *p)
static int setattr(Agobj_t *objp, char *name, char *val)
static Exnode_t * compile(Expr_t *prog, char *src, char *input, int line, const char *lbl, const char *sfx, int kind)
static void assignable(Agobj_t *objp, unsigned char *name)
static int convert(Exnode_t *x, long type, int arg)
static int setval(Expr_t *pgm, Exnode_t *x, Exid_t *sym, Exref_t *ref, void *env, Extype_t v)
static char * nxtAttr(Agraph_t *gp, char *k, char *name)
static Extype_t keyval(Extype_t v, long type)
static int ioflush(void *chan)
static Agiodisc_t gprIoDisc
static char * kindOf(Agobj_t *objp)
static void * int2ptr(long long i)
static void checkGuard(Exnode_t *gp, char *src, int line)
static int toKind(char *k, char *fn)
static int ioputstr(void *chan, const char *str)
static int isedge(Agobj_t *obj)
static int posOf(Agnode_t *np, int idx, double *v)
void errorf(void *handle, void *discipline, int level, const char *s,...)
void setErrorLine(int line)
void setErrorFileLine(char *src, int line)
void exdump(Expr_t *ex, Exnode_t *node, agxbuf *xb)
void exerror(const char *format,...)
char * exstring(Expr_t *ex, char *s)
void * exstralloc(Expr_t *ex, size_t sz)
Exnode_t * exexpr(Expr_t *ex, const char *name, Exid_t *sym, int type)
static NORETURN void graphviz_exit(int status)
Expr_t * exopen(Exdisc_t *disc)
int exisAssign(Exnode_t *)
void(* Exerror_f)(Expr_t *, Exdisc_t *, int, const char *,...)
Exnode_t * exnoncast(Exnode_t *)
void exclose(Expr_t *, int)
int excomp(Expr_t *p, const char *name, int line, FILE *fp, char *prefix)
Extype_t exzero(long int)
static char * typenames[]
static double len(glCompPoint p)
gvprbinding * findBinding(Gpr_t *state, char *fname)
bool validTVT(long long c)
int agnedges(Agraph_t *g)
int agdegree(Agraph_t *g, Agnode_t *n, int in, int out)
int agnnodes(Agraph_t *g)
size_t graphviz_node_induce(Agraph_t *g, Agraph_t *edgeset)
Agsym_t * agattrsym(void *obj, char *name)
looks up a string attribute for a graph object given as an argument
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Agsym_t * agnxtattr(Agraph_t *g, int kind, Agsym_t *attr)
permits traversing the list of attributes of a given type
int agxset(void *obj, Agsym_t *sym, const char *value)
char * agxget(void *obj, Agsym_t *sym)
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Agedge_t * agnxtin(Agraph_t *g, Agedge_t *e)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Agedge_t * agfstin(Agraph_t *g, Agnode_t *n)
int agisdirected(Agraph_t *g)
int agisstrict(Agraph_t *g)
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
Agraph_t * agread(void *chan, Agdisc_t *disc)
constructs a new graph
Agdesc_t Agdirected
directed
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
Agraph_t * agraphof(void *obj)
char * agnameof(void *)
returns a string descriptor for the object.
#define AGID(obj)
returns the unique integer ID associated with the object
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
int agcontains(Agraph_t *, void *obj)
returns non-zero if obj is a member of (sub)graph
Agraph_t * agroot(void *obj)
Agrec_t * aggetrec(void *obj, const char *name, int move_to_front)
find record in circular list and do optional move-to-front and lock
void aginit(Agraph_t *g, int kind, const char *rec_name, int rec_size, int move_to_front)
attach new records to objects of specified kind
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
int aghtmlstr(const char *)
Agraph_t * agparent(Agraph_t *g)
Agraph_t * agfstsubg(Agraph_t *g)
Agraph_t * agnxtsubg(Agraph_t *subg)
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
textitem scanner parser str
static void addEdge(edge_t *de, edge_t *e)
static void copyAttr(graph_t *g, graph_t *dg, char *attr)
static FILE * openFile(const char *argv0, const char *name, const char *mode)
static char * canon(graph_t *g, char *s)
#define PRISIZE_T
PRIu64 alike for printing size_t
static int label(Agnode_t *n, int nodecnt, int *edgecnt)
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
a generic header of Agraph_s, Agnode_s and Agedge_s
Extype_t(* reff)(Expr_t *, Exnode_t *, Exid_t *, Exref_t *)
Extype_t(* keyf)(Extype_t, long)
int(* convertf)(Exnode_t *, long, int)
int(* binaryf)(Exnode_t *, Exnode_t *, Exnode_t *, int)
Extype_t(* getf)(Expr_t *, Exnode_t *, Exid_t *, Exref_t *, void *, int, Exdisc_t *)
int(* stringof)(Expr_t *, Exnode_t *, int)
int(* setf)(Expr_t *, Exnode_t *, Exid_t *, Exref_t *, void *, Extype_t)
bool does_walk_graph
does this block have a node or edge statement?
bool uses_graph
does this program use the input graph?
struct Exdata_u::@87 variable
struct Exdata_u::@84 constant
void * vmalloc(Vmalloc_t *vm, size_t size)