dot 转换的一个小工具

A -> B -> C 我以为要分开写成A -> B; B -> C。另外我不想重复,比如A-> B; A-> C我想表示为A然后缩进一个空格写B,C。

于是有了下面的一个小工具。

/*indent text file to graphviz dot description
usage: cat in.txt | ./i2g | xdot

e.g.
indent and chains:
aaa -> bb
AAA
 BB -> bb -> cc
 CC -> dd
DD -> EE
"aa bb"
 alice
 "bob Bob"

with label for edges:
A -> D [label=ddd] -> E 

with label for nodes:
A D[label=ddd]  E

label for nodes and edges:
A D[label=ddd]  D -> E[label=eee] 
D[shape=circle, label=ddd] A -> D [label=ad, style = bold, shape = circle]  -> E[label=eee, color=red, style = dotted]

*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define STK 8
#define W 128
char stk[STK][128];

int get_attr(char *w, int s, char **ptr)
{//get "[any stuff here]"
	char *p = *ptr;
	char *q = w;
	int i, found = 0;
	while(*p && isspace(*p)){
		p++;
	}
	
	if(*p != '['){
		*w = 0;
		return 0;
	}
	for(i = 0; i < s - 1; ++i)
	{
		*w++ = *p++;
		if(w[-1] == ']'){
			found = 1;
			break;
		}
	}

	if(!found){
		w = q;
	}
	*w = 0;
	*ptr = p;

	return w - q; 
}

int get_node(char *w, int s, char **ptr)
{//get non-spaced string or quoted spaced string e.g. "aa bb "
	char *p = *ptr;
	char *q = w;
	int i, quote = 0;
	while(*p && isspace(*p)){
		p++;
	}
	if(*p == '"'){
		*w++ = *p++;
		quote = 1;
	}
	
	for(i = 0; i < s-1 && *p; ++i){
		if(1 == quote && *p == '"'){
			*w++ = *p++;
			break;
		}
		if(*p == '[')
			break;

		*w++ = *p++;
		if(!quote && isspace(*p)){
			break;
		}
	}
	*w = 0;
	*ptr = p;
	return w - q;
}

int output(char *from, char *to, char *attr)
{
	if(!from[0] || !to[0]){
		return -1;
	}

	fprintf(stdout, "%s -> %s %s;\n", from, to, attr);
	return 0;
}

int main(int ac, char **av)
{
	char line[1024];
	char w[W] = "", a[W] = "", last[W] = "", la[W] = "";
	char *ptr;
	int idt, flag, first, tail;
	
	fprintf(stdout, "digraph g {\nnode [shape=plaintext];\n");
	while(fgets(line, sizeof(line), stdin)){
		ptr = line;
		while(*ptr == ' '){ptr++;}
		idt = ptr - line;
		if(idt >= STK)idt = 0;
		first = 1;
		flag = 0;
		tail = 0;
		

		while(get_node(w, sizeof(w), &ptr)){
			get_attr(a, sizeof(a), &ptr);
			if(first){
				strcpy(stk[idt], w);
				first = 0;
			}
			if(w[0] == '-'){//"--" "->"
				flag = w[1] == '>' ? 1 : 2;
			}else{
				if(idt){//has indent
					output(stk[idt-1], w, a);
					a[0] = 0;
					strcpy(stk[idt], w);
					idt = 0;
				}else if(flag){//A -> B 
					output(last, w, a);
					a[0] = 0;
					flag = 0;
					tail = 0;
				}else if(!flag){//A B
					if(last[0])
						fprintf(stdout, "%s %s ", last, la);
					tail = 1;
				}
				strcpy(last, w);
				strcpy(la, a);
			}
		}
		if(tail && last[0])
			fprintf(stdout, "%s %s \n", last, la);
	}
	fprintf(stdout, "}\n");
	return 0;
}


参考
[1] dotguide.pdf

你可能感兴趣的:(format)