52 " [-o <ofile>] [-a <args>] ([-f <prog>] | 'prog') [files]\n\
53 -c - use source graph for output\n\
54 -f <pfile> - find program in file <pfile>\n\
55 -i - create node induced subgraph\n\
56 -a <args> - string arguments available as ARGV[0..]\n\
57 -o <ofile> - write output to <ofile>; stdout by default\n\
58 -n - no read-ahead of input graphs\n\
59 -q - turn off warning messages\n\
60 -v - enable verbose messages\n\
61 -V - print version info\n\
62 -? - print usage info\n\
63If no files are specified, stdin is used\n";
79 FILE *
const outs =
gv_fopen(name,
"w");
111 }
else if (!q && (c ==
'"' || c ==
'\'')) {
113 }
else if (c ==
'\\') {
120 "backslash in argument followed by no character - ignored");
152#if defined(_WIN32) && !defined(__MINGW32__)
158static char *
concat(
char *pfx,
char *sfx) {
196 const size_t share_len =
197 strlen(
".:") + strlen(exe) + strlen(
"/share/graphviz/gvpr") + 1;
198 char *
const share =
malloc(share_len);
203 snprintf(share, share_len,
".%c%s%cshare%cgraphviz%cgvpr",
LISTSEP, exe,
233 path = getenv(
"GVPRPATH");
235 path = getenv(
"GPRPATH");
247 fprintf(stderr,
"PATH: %s\n",
path);
257 sz = (size_t)(cp -
path);
267 if (access(
s, R_OK) == 0) {
280 fprintf(stderr,
"file %s resolved to %s\n", arg,
285static char *
getOptarg(
int c,
char **argp,
int *argip,
int argc,
char **argv) {
295 }
else if (argi < argc) {
317 while ((c = *arg++)) {
320 opts->compflags.srcout =
true;
323 opts->compflags.srcout =
true;
324 opts->compflags.clone =
true;
327 if ((optarg =
getOptarg(c, &arg, &argi, argc, argv)) &&
334 opts->compflags.induce =
true;
340 if ((optarg =
getOptarg(c, &arg, &argi, argc, argv))) {
346 if (!(optarg =
getOptarg(c, &arg, &argi, argc, argv)) ||
357 fprintf(stderr,
"%s version %s (%s)\n",
Info[0],
Info[1],
Info[2]);
360 if (optopt ==
'\0' || optopt ==
'?')
361 fprintf(stderr,
"Usage: gvpr%s",
usage);
376 fclose(
opts.outFile);
390 opts.cmdName = argv[0];
396 LIST(
char *) input_filenames = {0};
399 for (
int i = 1; i < argc;) {
412 if (
opts.useFile == 0) {
429 opts.outFile = stdout;
432 if (
opts.state <= 0) {
447 for (
size_t i = 0; i < xprog->
n_estmts; i++) {
469 for (
size_t i = 0; i < xprog->
n_nstmts; i++) {
497 state->
flags &= ~GV_NEXT_SET;
498 }
else if (nodes->
prev) {
506#define MARKED(x) (((x)->iu.integer) & 1)
507#define MARK(x) (((x)->iu.integer) = 1)
508#define ONSTACK(x) (((x)->iu.integer) & 2)
509#define PUSH(x, e) (((x)->iu.integer) |= 2, (x)->ine = (e))
510#define POP(x) (((x)->iu.integer) &= (~2))
552 while ((n =
nextNode(state, &nodes))) {
564 if (!
evalNode(state, prog, xprog, n))
566 for (cure =
agfstedge(g, n); cure; cure = nxte) {
571 if (!
evalEdge(state, prog, xprog, cure))
598 while ((n =
nextNode(state, &nodes))) {
618 if (entry ==
agopp(cure))
634 state->
tvedge = entry = cure;
649 if (entry == &
seed.out)
682 for (e =
agfstout(g, n); e; e = nexte) {
697 if (!
evalNode(state, prog, xprog, n))
700 for (e =
agfstout(g, n); e; e = nexte) {
748 switch (state->
tvt) {
855 if (
data->lock.locked)
856 data->lock.zombie =
true;
891 const char *fmt, ...) {
895 errorv((discipline && handle) ? *((
char **)handle) : (
char *)handle, level,
904 longjmp(state->
jbuf, 1);
972 bool incoreGraphs = uopts && uopts->
ingraphs;
975 fprintf(stderr,
"Parse/compile/init: %.2f secs.\n",
gvelapsed_sec());
993 fprintf(stderr,
"Read graph: %.2f secs.\n",
gvelapsed_sec());
1022 fprintf(stderr,
"Finish graph: %.2f secs.\n",
gvelapsed_sec());
1051 fprintf(stderr,
"Read graph: %.2f secs.\n",
gvelapsed_sec());
1075 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)
double gvelapsed_sec(void)
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)
static char * gettok(char **sp)
static FILE * openOut(char *name)
static bool traverse(Gpr_t *state, Expr_t *prog, comp_block *bp, bool 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)
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 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
Non-owning string references.
static strview_t strview(const char *referent, char terminator)
create a string reference