/* * Copyright (c) 2000-2001 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include "dot.h" #include "hash.h" static FILE *of; static hash_table node_hash_table; static region dot_region; static int node_count; static const char *edge_op; static void print_n_attrs(node_attr *attrs, int n) { int i; fputc('[',of); for (i = 0; i < n; i++) { const char *name; switch (attrs[i].name) { case n_color: name = "color"; break; case n_fontcolor: name = "fontcolor"; break; case n_fontname: name = "fontname"; break; case n_fontsize: name = "fontsize"; break; case n_height: name = "height"; break; case n_width: name = "width"; break; case n_label: name = "label"; break; case n_layer: name = "layer"; break; case n_shape: name = "shape"; break; case n_shapefile: name = "shapefile"; break; case n_style: name = "style"; break; default: name = ""; assert(0); break; } if (i > 0) fputc(',',of); fprintf(of,"%s = %s",name,attrs[i].value); } fputc(']',of); } static void print_e_attrs(edge_attr *attrs, int n) { int i; fputc('[',of); for (i = 0; i < n; i++) { const char *name; switch(attrs[i].name) { case e_color: name = "color"; break; case e_decorate: name = "decorate"; break; case e_dir: name = "dir"; break; case e_fontcolor: name = "fontcolor"; break; case e_fontname: name = "fontname"; break; case e_fontsize: name = "fontsize"; break; case e_id: name = "id"; break; case e_label: name = "label"; break; case e_layer: name = "layer"; break; case e_minlen: name = "minlen"; break; case e_style: name = "style"; break; case e_weight: name = "weight"; break; default : name = ""; assert(0); break; } if (i > 0) fputc(',',of); fprintf(of,"%s = %s",name,attrs[i].value); } fputc(']',of); } static void print_g_attrs(graph_attr *attrs, int n) { int i; fputc('[',of); for (i = 0; i < n; i++) { const char *name; switch (attrs[i].name) { case g_center: name = "center"; break; case g_clusterrank: name = "clusterrank"; break; case g_color: name = "color"; break; case g_concentrate: name = "concentrate"; break; case g_fontcolor: name = "fontcolor"; break; case g_fontname: name = "fontname"; break; case g_fontsize: name = "fontsize"; break; case g_label: name = "label"; break; case g_layerseq: name = "layerseq"; break; case g_margin: name = "margin"; break; case g_mclimit: name = "mclimit"; break; case g_nodesep: name = "nodesep"; break; case g_nslimit: name = "nslimit"; break; case g_ordering: name = "ordering"; break; case g_orientation: name = "orientation"; break; case g_page: name = "page"; break; case g_rank: name = "rank"; break; case g_rankdir: name = "rankdir"; break; case g_ranksep: name = "ranksep"; break; case g_ratio: name = "ratio"; break; case g_size: name = "size"; break; default : name = ""; assert(0); break; } if (i > 0) fputc(',',of); fprintf(of,"%s = %s",name,attrs[i].value); } fputc(']',of); } void dot_start(FILE *to,const char *name,bool is_directed,bool is_strict) { const char *graph_type,*strict; node_count = 0; dot_region = newregion(); node_hash_table = make_string_hash_table(dot_region,8,TRUE); of = to; if (is_directed) { edge_op = "->"; graph_type = "digraph"; } else { edge_op = "--"; graph_type = "graph"; } if (is_strict) strict = "strict"; else strict = ""; fprintf(of,"%s %s %s{\n",strict,graph_type,name); } void dot_global_graph_style(graph_attr *attrs, int n) { fputs("graph ",of); print_g_attrs(attrs,n); fputc(';',of); fputc('\n',of); } void dot_global_edge_style(edge_attr *attrs, int n) { fputs("edge ",of); print_e_attrs(attrs,n); fputc(';',of); fputc('\n',of); } void dot_global_node_style(node_attr *attrs, int n) { fputs("node ",of); print_n_attrs(attrs,n); fputc(';',of); fputc('\n',of); } /* by default, set the node's name to label */ static void declare_node(dot_node n, char *label) { int i; char mangled[512]; if (label[0] == '\"') mangled[0] = 's'; else mangled[0] = label[0]; for (i = 1; label[i] && i < 512 ;i++) { if (label[i] == '\"') mangled[i] = '_'; else mangled[i] = label[i]; } mangled[i] = '\0'; fprintf(of,"nd_%d [label=\"%s\"]\n",n,mangled); } dot_node dot_get_node(char *label) deletes { dot_node result; if (!hash_table_lookup(node_hash_table,(hash_key)label,(hash_data *)(char *)&result)) { dot_node newnode = node_count++; declare_node(newnode,label); hash_table_insert(node_hash_table, (hash_key)rstrdup(dot_region,label), (hash_data)newnode); return newnode; } else return result; } void dot_node_style(dot_node node,node_attr *attrs, int n) { fprintf(of,"nd_%d ",node); print_n_attrs(attrs,n); fputc(';',of); fputc('\n',of); } void dot_plain_edge(dot_node from, dot_node to) { fprintf(of,"nd_%d %s nd_%d;\n",from,edge_op,to); } void dot_styled_edge(dot_node from, dot_node to, edge_attr *attrs, int n) { fprintf(of,"nd_%d %s nd_%d ",from,edge_op,to); print_e_attrs(attrs,n); fputc(';',of); fputc('\n',of); } void dot_end(void) deletes { fputc('}',of); hash_table_delete(node_hash_table); deleteregion_ptr(&dot_region); }