53 " [-o <ofile>] [-a <args>] ([-f <prog>] | 'prog') [files]\n\
54 -c - use source graph for output\n\
55 -f <pfile> - find program in file <pfile>\n\
56 -i - create node induced subgraph\n\
57 -a <args> - string arguments available as ARGV[0..]\n\
58 -o <ofile> - write output to <ofile>; stdout by default\n\
59 -n - no read-ahead of input graphs\n\
60 -q - turn off warning messages\n\
61 -v - enable verbose messages\n\
62 -V - print version info\n\
63 -? - print usage info\n\
64If no files are specified, stdin is used\n";
82 const clock_t end = clock();
83 return (end - start) / (double)CLOCKS_PER_SEC;
87 FILE *
const outs =
gv_fopen(name,
"w");
118 }
else if (!q && (c ==
'"' || c ==
'\'')) {
120 }
else if (c ==
'\\') {
127 "backslash in argument followed by no character - ignored");
158#if defined(_WIN32) && !defined(__MINGW32__)
164static char *
concat(
char *pfx,
char *sfx) {
202 const size_t share_len =
203 strlen(
".:") + strlen(exe) + strlen(
"/share/graphviz/gvpr") + 1;
204 char *
const share =
malloc(share_len);
209 snprintf(share, share_len,
".%c%s%cshare%cgraphviz%cgvpr",
LISTSEP, exe,
238 path = getenv(
"GVPRPATH");
240 path = getenv(
"GPRPATH");
252 fprintf(stderr,
"PATH: %s\n",
path);
262 sz = (size_t)(cp -
path);
272 if (access(
s, R_OK) == 0) {
285 fprintf(stderr,
"file %s resolved to %s\n", arg,
290static char *
getOptarg(
int c,
char **argp,
int *argip,
int argc,
char **argv) {
300 }
else if (argi < argc) {
321 while ((c = *arg++)) {
324 opts->compflags.srcout =
true;
327 opts->compflags.srcout =
true;
328 opts->compflags.clone =
true;
331 if ((optarg =
getOptarg(c, &arg, &argi, argc, argv)) &&
338 opts->compflags.induce =
true;
344 if ((optarg =
getOptarg(c, &arg, &argi, argc, argv))) {
350 if (!(optarg =
getOptarg(c, &arg, &argi, argc, argv)) ||
361 fprintf(stderr,
"%s version %s (%s)\n",
Info[0],
Info[1],
Info[2]);
364 if (optopt ==
'\0' || optopt ==
'?')
365 fprintf(stderr,
"Usage: gvpr%s",
usage);
380 fclose(
opts.outFile);
392 opts.cmdName = argv[0];
398 LIST(
char *) input_filenames = {0};
401 for (
int i = 1; i < argc;) {
414 if (
opts.useFile == 0) {
431 opts.outFile = stdout;
434 if (
opts.state <= 0) {
449 for (
size_t i = 0; i < xprog->
n_estmts; i++) {
471 for (
size_t i = 0; i < xprog->
n_nstmts; i++) {
499 state->
flags &= ~GV_NEXT_SET;
500 }
else if (nodes->
prev) {
508#define MARKED(x) (((x)->iu.integer) & 1)
509#define MARK(x) (((x)->iu.integer) = 1)
510#define ONSTACK(x) (((x)->iu.integer) & 2)
511#define PUSH(x, e) (((x)->iu.integer) |= 2, (x)->ine = (e))
512#define POP(x) (((x)->iu.integer) &= (~2))
554 while ((n =
nextNode(state, &nodes))) {
566 if (!
evalNode(state, prog, xprog, n))
568 for (cure =
agfstedge(g, n); cure; cure = nxte) {
573 if (!
evalEdge(state, prog, xprog, cure))
600 while ((n =
nextNode(state, &nodes))) {
620 if (entry ==
agopp(cure))
636 state->
tvedge = entry = cure;
651 if (entry == &
seed.out)
684 for (e =
agfstout(g, n); e; e = nexte) {
699 if (!
evalNode(state, prog, xprog, n))
702 for (e =
agfstout(g, n); e; e = nexte) {
746 switch (state->
tvt) {
887 const char *fmt, ...) {
891 errorv((discipline && handle) ? *((
char **)handle) : (
char *)handle, level,
900 longjmp(state->
jbuf, 1);
963 bool incoreGraphs = uopts->
ingraphs;
966 fprintf(stderr,
"Parse/compile/init: %.2f secs.\n",
elapsed_sec(start));
983 fprintf(stderr,
"Read graph: %.2f secs.\n",
elapsed_sec(start));
1012 fprintf(stderr,
"Finish graph: %.2f secs.\n",
elapsed_sec(start));
1040 fprintf(stderr,
"Read graph: %.2f secs.\n",
elapsed_sec(start));
1065 if (uopts ==
NULL) {
1066 uopts = &DEFAULT_OPTS;
1069 int rv =
gvpr_core(argc, argv, uopts, &gvpr_state);
Agobj_t * cloneO(Agraph_t *g, Agobj_t *obj)
int sfioWrite(Agraph_t *g, FILE *fp)
static void agxbfree(agxbuf *xb)
free any malloced resources
static size_t agxbput_n(agxbuf *xb, const char *s, size_t ssz)
append string s of length ssz into xb
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
static char * agxbdisown(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
static char * gv_strdup(const char *original)
abstract graph C library, Cgraph API
comp_prog * compileProg(parse_prog *inp, Gpr_t *state, compflags_t flags)
Agraph_t * openSubg(Agraph_t *g, char *name)
void freeCompileProg(comp_prog *p)
void setTraceLevel(int i)
void errorv(const char *id, int level, const char *s, va_list ap)
void setErrorId(char *id)
void setErrorErrors(int errors)
Extype_t exeval(Expr_t *ex, Exnode_t *exnode, void *env)
static NORETURN void graphviz_exit(int status)
static void cleanup(void)
void initGPRState(Gpr_t *state)
void addBindings(Gpr_t *state, gvprbinding *bindings)
Gpr_t * openGPRState(gpr_info *info)
void closeGPRState(Gpr_t *state)
int agnnodes(Agraph_t *g)
#define agopp(e)
opposite edge: flip Agedgepair_s.out ⇄ Agedgepair_s.in/*#end#*/
Agedge_t * agsubedge(Agraph_t *g, Agedge_t *e, 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 agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Agraph_t * agconcat(Agraph_t *g, const char *filename, void *chan, Agdisc_t *disc)
merges the file contents with a pre-existing graph
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Agraph_t * agroot(void *obj)
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
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
replacements for ctype.h functions
static bool gv_isspace(int c)
platform abstraction for finding the path to yourself
FILE * gv_fopen(const char *filename, const char *mode)
wrapper around fopen for internal library usage
static void freeOpts(options opts)
static char * concat(char *pfx, char *sfx)
static char * resolve(char *arg, int verbose)
static Agobj_t * evalNode(Gpr_t *state, Expr_t *prog, comp_block *xprog, Agnode_t *n)
static void gvexitf(void *env, int v)
int gvpr(int argc, char *argv[], gvpropts *uopts)
static void chkClose(Agraph_t *g)
static void travNodes(Gpr_t *state, Expr_t *prog, comp_block *xprog)
static void doCleanup(Agraph_t *g)
reset node traversal data
static char * gettok(char **sp)
static FILE * openOut(char *name)
static bool traverse(Gpr_t *state, Expr_t *prog, comp_block *bp, bool cleanup)
return true if traversal requires cleanup
static Agedge_t * agnxtin_(Agraph_t *g, Agedge_t *e, Agnode_t *ignored)
agnxtin wrapper to tweak calling convention
Agedge_t *(* nxttedgefn_t)(Agraph_t *, Agedge_t *, Agnode_t *)
static options scanArgs(int argc, char **argv)
parse command line options
static void travDFS(Gpr_t *state, Expr_t *prog, comp_block *xprog, trav_fns *fns)
static void travBFS(Gpr_t *state, Expr_t *prog, comp_block *xprog)
static void travFlat(Gpr_t *state, Expr_t *prog, comp_block *xprog)
static clock_t start_timer(void)
static char * dflt_gvprpath(void)
static void travEdges(Gpr_t *state, Expr_t *prog, comp_block *xprog)
static Agraph_t * ing_read(const char *filename, void *fp)
static Agnode_t * nextNode(Gpr_t *state, nodestream *nodes)
static void addOutputGraph(Gpr_t *state, gvpropts *uopts)
static int gvpr_core(int argc, char *argv[], gvpropts *uopts, gvpr_state_t *gs)
static int doFlags(char *arg, int argi, int argc, char **argv, options *opts)
static void gverrorf(Expr_t *handle, Exdisc_t *discipline, int level, const char *fmt,...)
Agedge_t *(* fstedgefn_t)(Agraph_t *, Agnode_t *)
static Agedge_t * agnxtout_(Agraph_t *g, Agedge_t *e, Agnode_t *ignored)
agnxtout wrapper to tweak calling convention
static const char * usage
static Agobj_t * evalEdge(Gpr_t *state, Expr_t *prog, comp_block *xprog, Agedge_t *e)
static void parseArgs(char *s, strviews_t *arg)
static char * getOptarg(int c, char **argp, int *argip, int argc, char **argv)
graph pattern scanning and processing language API, main function gvpr
char * fileName(ingraph_state *sp)
Return name of current file being processed.
void closeIngraph(ingraph_state *sp)
Agraph_t * nextGraph(ingraph_state *sp)
ingraph_state * newIng(ingraph_state *sp, char **files, Agraph_t *(*readf)(const char *, void *))
ingraph_state * newIngGraphs(ingraph_state *sp, Agraph_t **graphs, Agraph_t *(*readf)(const char *, void *))
supports user-supplied data
type-generic dynamically expanding list
#define LIST_DETACH(list, datap, sizep)
#define LIST_POP_FRONT(list)
#define LIST_APPEND(list, item)
#define LIST_POP_BACK(list)
#define LIST_IS_EMPTY(list)
#define LIST_PUSH_BACK(list, item)
void freeParseProg(parse_prog *prog)
parse_prog * parseProg(char *input, int isFile)
parses input into gpr sections
File system path helpers.
#define PATH_SEPARATOR
character for separating directory components in a file system path
a generic header of Agraph_s, Agnode_s and Agedge_s
bool does_walk_graph
does this block have a node or edge statement?
bool uses_graph
does this program use the input graph?
collective managed state used in gvpr_core
size_t n_outgraphs
if GV_USE_OUTGRAPH set, output graphs
bool zombie
was a deletion request recorded while locked?
bool locked
is the lock currently taken?
Non-owning string references.
static strview_t strview(const char *referent, char terminator)
create a string reference