56 {
"gvplugin_neato_layout_LTX_library", 0 },
91static char*
gname =
const_cast<char*
>(
"root");
93#define NEWNODE(n) ((node_t*)ND_alg(n))
96 "Usage: gvpack [-gnuv?] [-m<margin>] {-array[_rc][n]] [-o<outf>] <files>\n\
97 -n - use node granularity\n\
98 -g - use graph granularity\n\
99 -array* - pack as array of graphs\n\
100 -G<n>=<v> - attach name/value attribute to output graph\n\
101 -m<n> - set margin to <n> points\n\
102 -s<gname> - use <gname> for name of root graph\n\
103 -o<outfile> - write output to <outfile>\n\
104 -u - no packing; just combine graphs\n\
107If no files are specified, stdin is used\n";
121 char *rhs =
const_cast<char*
>(
"true");
123 if (
char *p = strchr(arg,
'=')) {
141 i = (
unsigned int) strtol(arg, &p, 10);
143 std::cerr <<
"Error: bad value in flag -" << (arg - 1) <<
" - ignored\n";
170 pinfo->
fixed =
nullptr;
174 while ((c = getopt(argc, argv,
":na:gvum:s:o:G:?")) != -1) {
177 auto buf = std::string(
"a") + optarg +
"\n";
194 if (
outfp !=
nullptr)
205 std::cerr <<
"gvpack: option -G missing argument - ignored\n";
212 std::cerr <<
"gvpack: option -" << (char)optopt
213 <<
" missing argument - ignored\n";
216 if (optopt ==
'\0' || optopt ==
'?')
219 std::cerr <<
"gvpack: option -" << (char)optopt <<
" unrecognized\n";
234 std::cerr <<
" margin " << pinfo->
margin <<
'\n';
275 std::cerr <<
"Error: graph " <<
agnameof(g) <<
" has dim = " << d
284 std::cerr <<
"Error loading layout info from graph " <<
agnameof(g) <<
'\n';
286 std::cerr <<
"gvpack does not support backgrounds as found in graph "
374struct AttributeValue {
391 char *name = a->name;
392 char *value = a->defval;
393 auto it = newdict.find(name);
394 if (it == newdict.end()) {
395 newdict.insert({name, AttributeValue{value, 1}});
396 }
else if (it->second.value == value)
397 ++it->second.instances;
410 for (
const auto &kv : d) {
411 const std::string &name = kv.first;
412 const std::string &value = kv.second.value;
413 const size_t &attr_cnt = kv.second.instances;
415 setf(g,
const_cast<char *
>(name.c_str()), value.c_str());
417 setf(g,
const_cast<char *
>(name.c_str()),
"");
449using used_t = std::multiset<std::string>;
459 size_t previous_instances = names.count(oldname);
460 names.insert(oldname);
461 if (previous_instances > 0) {
462 return std::string(oldname) +
"_gv" + std::to_string(previous_instances);
467#define MARK(e) (ED_alg(e) = e)
468#define MARKED(e) (ED_alg(e))
469#define SETCLUST(g,h) (GD_alg(g) = h)
470#define GETCLUST(g) ((Agraph_t*)GD_alg(g))
519 ne =
agedge(ng, nt, nh,
nullptr, 1);
562 std::cerr <<
"Creating clone graph\n";
571 agxset(root, rv, a.value);
582 for (
size_t i = 0; i < gs.size(); i++) {
585 std::cerr <<
"Cloning graph " <<
agnameof(g) <<
'\n';
592 std::cerr <<
"Warning: node " <<
agnameof(n) <<
" in graph[" << i <<
"] "
593 <<
agnameof(g) <<
" already defined\n"
594 <<
"Some nodes will be renamed.\n";
640 std::vector<Agraph_t*> gs;
651 std::cerr <<
"Reading graph " <<
agnameof(g) <<
'\n';
653 std::cerr <<
"Graph " <<
agnameof(g) <<
" is empty - ignoring\n";
661 std::cerr <<
"Error: all graphs must be directed or undirected\n";
681 for (
size_t i = 1; i < gs.size(); i++) {
713 std::cerr <<
"====\n";
718int main(
int argc,
char *argv[])
724 init(argc, argv, &pinfo);
738 if (
packGraphs(gs.size(), gs.data(), 0, &pinfo)) {
739 std::cerr <<
"gvpack: packing of graphs failed.\n";
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
void common_init_edge(edge_t *e)
bool is_a_cluster(Agraph_t *g)
#define agnodeattr(g, n, v)
static NORETURN void graphviz_exit(int status)
static int cnt(Dict_t *d, Dtlink_t **set)
int agnnodes(Agraph_t *g)
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
int agset(void *obj, char *name, const char *value)
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 * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
#define agfindgraphattr(g, a)
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
int agwrite(Agraph_t *g, void *chan)
Return 0 on success, EOF on failure.
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)
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
#define agfindnodeattr(g, a)
char * agnameof(void *)
returns a string descriptor for the object.
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
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
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 *)
int agstrfree(Agraph_t *, const char *)
char * agstrdup_html(Agraph_t *, const char *)
Agraph_t * agfstsubg(Agraph_t *g)
Agraph_t * agnxtsubg(Agraph_t *subg)
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
GVC_t * gvContextPlugins(const lt_symlist_t *builtins, int demand_loading)
void attach_attrs(graph_t *g)
#define agedgeattr(g, n, s)
#define agraphattr(g, n, s)
Graphviz context library.
static void cloneClusterTree(Agraph_t *g, Agraph_t *ng)
static void cloneCluster(Agraph_t *old, Agraph_t *new_cluster)
static std::vector< Agraph_t * > readGraphs(GVC_t *gvc)
std::multiset< std::string > used_t
names that have already been used during generation
static void init_node_edge(Agraph_t *g)
lt_symlist_t lt_preloaded_symbols[]
static std::vector< attr_t > G_args
static Agraph_t * cloneGraph(std::vector< Agraph_t * > &gs, GVC_t *gvc)
static int setNameValue(char *arg)
static void init_graph(Agraph_t *g, bool fill, GVC_t *gvc)
static void cloneSubg(Agraph_t *g, Agraph_t *ng, Agsym_t *G_bb, used_t &gnames)
static void cloneNode(Agnode_t *old, Agnode_t *new_node)
static boxf compBB(std::vector< Agraph_t * > &gs)
static void cloneDfltAttrs(Agraph_t *old, Agraph_t *new_graph, int kind)
static void fillDict(attr_map_t &newdict, Agraph_t *g, int kind)
static std::string xName(used_t &names, char *oldname)
static void cloneEdge(Agedge_t *old, Agedge_t *new_edge)
static void fillGraph(Agraph_t *g, const attr_map_t &d, Agsym_t *(*setf)(Agraph_t *, char *, const char *), size_t cnt)
static int setUInt(unsigned int *v, char *arg)
static const char useString[]
static void cloneGraphAttr(Agraph_t *g, Agraph_t *ng)
static void initAttrs(Agraph_t *root, std::vector< Agraph_t * > &gs)
static void cloneAttrs(void *old, void *new_graph)
static void init(int argc, char *argv[], pack_info *pinfo)
std::map< std::string, AttributeValue > attr_map_t
attribute name → value collection of those we have seen
gvplugin_library_t gvplugin_neato_layout_LTX_library
static const char * usage
Agraph_t * nextGraph(ingraph_state *sp)
ingraph_state * newIngraph(ingraph_state *sp, char **files)
supports user-supplied data
bool user_pos(attrsym_t *posptr, attrsym_t *pinptr, node_t *np, int nG)
int init_nop(Agraph_t *g, int adjust)
void neato_init_node(node_t *n)
static FILE * openFile(const char *argv0, const char *name, const char *mode)
pack_mode parsePackModeInfo(const char *p, pack_mode dflt, pack_info *pinfo)
int packGraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
support for connected components
void dotneato_postprocess(Agraph_t *g)
bool doSplines
use splines in constructing graph shape