56 {
"gvplugin_neato_layout_LTX_library", 0 },
82static char*
gname =
const_cast<char*
>(
"root");
84#define NEWNODE(n) ((node_t*)ND_alg(n))
87 "Usage: gvpack [-gnuv?] [-m<margin>] {-array[_rc][n]] [-o<outf>] <files>\n\
88 -n - use node granularity\n\
89 -g - use graph granularity\n\
90 -array* - pack as array of graphs\n\
91 -G<n>=<v> - attach name/value attribute to output graph\n\
92 -m<n> - set margin to <n> points\n\
93 -s<gname> - use <gname> for name of root graph\n\
94 -o<outfile> - write output to <outfile>\n\
95 -u - no packing; just combine graphs\n\
98If no files are specified, stdin is used\n";
112 char *rhs =
const_cast<char*
>(
"true");
114 if (
char *p = strchr(arg,
'=')) {
132 i = (
unsigned int) strtol(arg, &p, 10);
134 std::cerr <<
"Error: bad value in flag -" << (arg - 1) <<
" - ignored\n";
161 pinfo->
fixed =
nullptr;
165 while ((c = getopt(argc, argv,
":na:gvum:s:o:G:?")) != -1) {
168 auto buf = std::string(
"a") + optarg +
"\n";
185 if (
outfp !=
nullptr)
196 std::cerr <<
"gvpack: option -G missing argument - ignored\n";
203 std::cerr <<
"gvpack: option -" << (char)optopt
204 <<
" missing argument - ignored\n";
207 if (optopt ==
'\0' || optopt ==
'?')
210 std::cerr <<
"gvpack: option -" << (char)optopt <<
" unrecognized\n";
225 std::cerr <<
" margin " << pinfo->
margin <<
'\n';
266 std::cerr <<
"Error: graph " <<
agnameof(g) <<
" has dim = " << d
275 std::cerr <<
"Error loading layout info from graph " <<
agnameof(g) <<
'\n';
277 std::cerr <<
"gvpack does not support backgrounds as found in graph "
309 int attr_kind =
AGTYPE(old);
365struct AttributeValue {
382 char *name = a->name;
383 char *value = a->defval;
384 auto it = newdict.find(name);
385 if (it == newdict.end()) {
386 newdict.insert({name, AttributeValue{value, 1}});
387 }
else if (it->second.value == value)
388 ++it->second.instances;
401 for (
const auto &kv : d) {
402 const std::string &name = kv.first;
403 const std::string &value = kv.second.value;
404 const size_t &attr_cnt = kv.second.instances;
406 setf(g,
const_cast<char *
>(name.c_str()), value.c_str());
408 setf(g,
const_cast<char *
>(name.c_str()),
"");
440using used_t = std::multiset<std::string>;
450 size_t previous_instances = names.count(oldname);
451 names.insert(oldname);
452 if (previous_instances > 0) {
453 return std::string(oldname) +
"_gv" + std::to_string(previous_instances);
458#define MARK(e) (ED_alg(e) = e)
459#define MARKED(e) (ED_alg(e))
460#define SETCLUST(g,h) (GD_alg(g) = h)
461#define GETCLUST(g) ((Agraph_t*)GD_alg(g))
509 ne =
agedge(ng, nt, nh,
nullptr, 1);
553 std::cerr <<
"Creating clone graph\n";
562 agxset(root, rv, a.value);
573 for (
size_t i = 0; i < gs.size(); i++) {
576 std::cerr <<
"Cloning graph " <<
agnameof(g) <<
'\n';
583 std::cerr <<
"Warning: node " <<
agnameof(n) <<
" in graph[" << i <<
"] "
584 <<
agnameof(g) <<
" already defined\n"
585 <<
"Some nodes will be renamed.\n";
631 std::optional<Agdesc_t> &kind) {
632 std::vector<Agraph_t*> gs;
642 std::cerr <<
"Reading graph " <<
agnameof(g) <<
'\n';
644 std::cerr <<
"Graph " <<
agnameof(g) <<
" is empty - ignoring\n";
647 if (!kind.has_value()) {
651 std::cerr <<
"Error: all graphs must be directed or undirected\n";
671 for (
size_t i = 1; i < gs.size(); i++) {
703 std::cerr <<
"====\n";
708int main(
int argc,
char *argv[])
714 init(argc, argv, &pinfo);
722 std::optional<Agdesc_t> kind;
729 if (
packGraphs(gs.size(), gs.data(), 0, &pinfo)) {
730 std::cerr <<
"gvpack: packing of graphs failed.\n";
736 assert(kind.has_value());
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 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 void cloneDfltAttrs(Agraph_t *old, Agraph_t *new_graph, int attr_kind)
static Agraph_t * cloneGraph(std::vector< Agraph_t * > &gs, GVC_t *gvc, Agdesc_t kind)
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 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 fillDict(attr_map_t &newdict, Agraph_t *g, int attr_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 std::vector< Agraph_t * > readGraphs(GVC_t *gvc, std::optional< Agdesc_t > &kind)
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 Agsym_t * agedgeattr(Agraph_t *g, char *name, const char *value)
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