dotter

graphiz helpers
git clone git://deadbeef.fr/dotter.git
Log | Files | Refs | README | LICENSE

uml (3934B)


      1 #!/usr/bin/awk -f
      2 
      3 function is_class( identifier ) {
      4 	return identifier == "struct" || identifier == "class";
      5 }
      6 
      7 function print_ft_name() {
      8 	printf( "\"" );
      9 	for( i = 2; i < NF; ++i )
     10 	{
     11 		printf( "%s ", $i );
     12 	}
     13 	printf( "%s\"", $NF );
     14 }
     15 
     16 function end_class() {
     17 	if( class != "" )
     18 	{
     19 		printf( "}\"\n]\n" );
     20 		prev_class = class;
     21 		class = "";
     22 	}
     23 	class_type = "";
     24 	inside = "";
     25 	fields_max = 0
     26 	fields_cur = 0
     27 }
     28 
     29 function fun( overload ) {
     30 	if( inside != "fun" )
     31 	{
     32 		printf( "|" );
     33 		inside = "fun";
     34 	}
     35 	printf( "%s %s(", scope, $3 )
     36 	for( i = 4; i <= NF; ++i )
     37 	{
     38 		gsub( ":", " ", $i );
     39 		printf( "%s%s", i == 4 ? "" : ", ", $i );
     40 	}
     41 	printf( "): %s %s\l", $2, overload );
     42 }
     43 
     44 function relation( to, tail, head, label, multiplicity ) {
     45 	printf( "%s -> %s [ dir = \"both\", arrowtail = \"%s\", arrowhead = \"%s\"", prev_class, to, tail, head );
     46 	if( label != "" )
     47 	{
     48 		printf( ", label = \"%s\"", label );
     49 	}
     50 	if( multiplicity != "" )
     51 	{
     52 		if( multiplicity ~ /[0-9]*:[0-9n]*/ )
     53 		{
     54 			split( multiplicity, labels, ":" );
     55 			printf( ", taillabel = \"%s\", headlabel = \"%s\"", labels[1], labels[2] );
     56 		}
     57 		else
     58 		{
     59 			printf( ", headlabel = \"%s\"", multiplicity );
     60 		}
     61 	}
     62 }
     63 
     64 function close_relation() {
     65 	printf( " ];\n" );
     66 }
     67 
     68 function depends( type ) {
     69 	end_class();
     70 	relation( $2, "none", "vee", type );
     71 	printf( " style = \"dotted\"" );
     72 	close_relation();
     73 }
     74 
     75 BEGIN {
     76 	printf( "digraph %s\n{\n", FILENAME );
     77 	class = "";
     78 	prev_class = "";
     79 	class_type = "";
     80 	inside = "";
     81 }
     82 
     83 $0 ~ "^[ \t]*private"   { scope = "[-]"; }
     84 $0 ~ "^[ \t]*protected" { scope = "[#]"; }
     85 $0 ~ "^[ \t]*public"    { scope = "[+]"; }
     86 $0 == "package"   { scope = "[~]"; }
     87 
     88 $1 == "splines" {
     89 	end_class();
     90 	printf( "splines = %s;\n", $2 );
     91 }
     92 
     93 $1 == "package_font" {
     94 	end_class();
     95 	printf( "fontname = " );
     96 	print_ft_name();
     97 	printf( ";\n" );
     98 }
     99 
    100 $1 == "class_font" {
    101 	end_class();
    102 	printf( "node [fontname = " );
    103 	print_ft_name();
    104 	printf( "];\n" );
    105 }
    106 
    107 $1 == "link_font" {
    108 	end_class();
    109 	printf( "edge [fontname = " );
    110 	print_ft_name();
    111 	printf( "];\n" );
    112 }
    113 
    114 $1 == "enum" || $1 == "bitfield" || is_class( $1 ) {
    115 	end_class();
    116 
    117 	if( NF == 3 )
    118 	{
    119 		fields_max = $3
    120 		fields_cur = 0
    121 	}
    122 	scope = "[ ]";
    123 	printf( "\n\n" );
    124 	class = $2;
    125 	class_type = $1;
    126 	special = ""; # for templates, enums, bitfields, structs (why not)...
    127 	if ( class_type != "class" )
    128 	{
    129 		scope = "";
    130 		special = "«" class_type;
    131 		if ( fields_max != 0 )
    132 		{
    133 			special = special "(" fields_max ")";
    134 		}
    135 		special = special "» ";
    136 	}
    137 	printf( "%s\n[\n\tshape=\"record\";\n\tlabel=\"{%s%s", class, special, class );
    138 }
    139 
    140 $1 == "fun" {
    141 	fun( "" );
    142 }
    143 
    144 $1 == "virtual" {
    145 	fun( "[[VIRT]]" );
    146 }
    147 
    148 $1 == "abstract" {
    149 	fun( "[[ABST]]" );
    150 }
    151 
    152 $1 == "var" {
    153 	if( inside != "var" )
    154 	{
    155 		printf( "|" );
    156 		inside = "var";
    157 	}
    158 	printf( "%s%s: %s", scope, $3, $2 );
    159 	if( NF == 4 )
    160 	{
    161 		printf( " = %s", $4 );
    162 	}
    163 	printf( "\l" );
    164 }
    165 
    166 $1 == "val" {
    167 	if( inside != "val" )
    168 	{
    169 		printf( "|" );
    170 		inside = "val";
    171 	}
    172 	error = "";
    173 	if ( fields_max != 0 )
    174 	{
    175 		++fields_cur;
    176 		if ( fields_cur > fields_max )
    177 		{
    178 			error = "EE: "
    179 		}
    180 	}
    181 	if ( is_class( class_type ) )
    182 	{
    183 		printf( "%s%s %s", error, scope, $2 );
    184 	}
    185 	else
    186 	{
    187 		if ( fields_max != 0 )
    188 		{
    189 			printf( "%s%d: %s", error, fields_cur, $2 );
    190 		}
    191 		else
    192 		{
    193 			printf( "%s%s", error, $2 );
    194 		}
    195 	}
    196 	printf( "\l" );
    197 }
    198 
    199 $1 == "inherit" {
    200 	end_class();
    201 	relation( $2, "none", "empty" );
    202 	close_relation();
    203 }
    204 
    205 $1 == "associate" {
    206 	end_class();
    207 	relation( $2, "none", "vee", $3, $4 );
    208 	close_relation();
    209 }
    210 
    211 $1 == "aggreg" {
    212 	end_class();
    213 	relation( $2, "odiamond", "vee", $3, $4 );
    214 	close_relation();
    215 }
    216 
    217 $1 == "compose" {
    218 	end_class();
    219 	relation( $2, "diamond", "vee", $3, $4 );
    220 	close_relation();
    221 }
    222 
    223 $1 == "depends" {
    224 	depends( "" );
    225 }
    226 
    227 $1 == "friend" {
    228 	depends( "friend" );
    229 }
    230 
    231 $1 == "package" {
    232 	end_class();
    233 	printf( "\nsubgraph cluster%s\n{\nlabel = \"%s\" ", $2, $2 );
    234 }
    235 
    236 $1 == "endpackage" {
    237 	end_class();
    238 	printf( "}\n" );
    239 }
    240 
    241 END {
    242 	end_class();
    243 	printf( "}\n" );
    244 }