rminnichmerge57758a716 years agoHistory
267 lines · 4.6 KB · C
RawDownload
#include "rc.h"#include "io.h"#include "fns.h"char nl='\n';		/* change to semicolon for bourne-proofing */#define	c0	t->child[0]#define	c1	t->child[1]#define	c2	t->child[2] voidpdeglob(io *f, char *s){	while(*s){		if(*s==GLOB)			s++;		pchr(f, *s++);	}} voidpcmd(io *f, tree *t){	if(t==0)		return;	switch(t->type){	default:	pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2);	break;	case '$':	pfmt(f, "$%t", c0);	break;	case '"':	pfmt(f, "$\"%t", c0);	break;	case '&':	pfmt(f, "%t&", c0);	break;	case '^':	pfmt(f, "%t^%t", c0, c1);	break;	case '`':	pfmt(f, "`%t", c0);	break;	case ANDAND:	pfmt(f, "%t && %t", c0, c1);	break;	case BANG:	pfmt(f, "! %t", c0);	break;	case BRACE:	pfmt(f, "{%t}", c0);	break;	case COUNT:	pfmt(f, "$#%t", c0);	break;	case FN:	pfmt(f, "fn %t %t", c0, c1);	break;	case IF:	pfmt(f, "if%t%t", c0, c1);	break;	case NOT:	pfmt(f, "if not %t", c0);	break;	case OROR:	pfmt(f, "%t || %t", c0, c1);	break;	case PCMD:	case PAREN:	pfmt(f, "(%t)", c0);	break;	case SUB:	pfmt(f, "$%t(%t)", c0, c1);	break;	case SIMPLE:	pfmt(f, "%t", c0);	break;	case SUBSHELL:	pfmt(f, "@ %t", c0);	break;	case SWITCH:	pfmt(f, "switch %t %t", c0, c1);	break;	case TWIDDLE:	pfmt(f, "~ %t %t", c0, c1);	break;	case WHILE:	pfmt(f, "while %t%t", c0, c1);	break;	case ARGLIST:		if(c0==0)			pfmt(f, "%t", c1);		else if(c1==0)			pfmt(f, "%t", c0);		else			pfmt(f, "%t %t", c0, c1);		break;	case ';':		if(c0){			if(c1)				pfmt(f, "%t%c%t", c0, nl, c1);			else pfmt(f, "%t", c0);		}		else pfmt(f, "%t", c1);		break;	case WORDS:		if(c0)			pfmt(f, "%t ", c0);		pfmt(f, "%t", c1);		break;	case FOR:		pfmt(f, "for(%t", c0);		if(c1)			pfmt(f, " in %t", c1);		pfmt(f, ")%t", c2);		break;	case WORD:		if(t->quoted)			pfmt(f, "%Q", t->str);		else pdeglob(f, t->str);		break;	case DUP:		if(t->rtype==DUPFD)			pfmt(f, ">[%d=%d]", t->fd1, t->fd0); /* yes, fd1, then fd0; read lex.c */		else			pfmt(f, ">[%d=]", t->fd0);		pfmt(f, "%t", c1);		break;	case PIPEFD:	case REDIR:		switch(t->rtype){		case HERE:			pchr(f, '<');		case READ:		case RDWR:			pchr(f, '<');			if(t->rtype==RDWR)				pchr(f, '>');			if(t->fd0!=0)				pfmt(f, "[%d]", t->fd0);			break;		case APPEND:			pchr(f, '>');		case WRITE:			pchr(f, '>');			if(t->fd0!=1)				pfmt(f, "[%d]", t->fd0);			break;		}		pfmt(f, "%t", c0);		if(c1)			pfmt(f, " %t", c1);		break;	case '=':		pfmt(f, "%t=%t", c0, c1);		if(c2)			pfmt(f, " %t", c2);		break;	case PIPE:		pfmt(f, "%t|", c0);		if(t->fd1==0){			if(t->fd0!=1)				pfmt(f, "[%d]", t->fd0);		}		else pfmt(f, "[%d=%d]", t->fd0, t->fd1);		pfmt(f, "%t", c1);		break;	case FANIN:		pfmt(f, "%t>|", c0);		if(t->fd1==0){			if(t->fd0!=1)				pfmt(f, "[%d]", t->fd0);		}		else pfmt(f, "[%d=%d]", t->fd0, t->fd1);		pfmt(f, "%t", c1);		break;	case FANOUT:		pfmt(f, "%t|<", c0);		if(t->fd1==0){			if(t->fd0!=1)				pfmt(f, "[%d]", t->fd0);		}		else pfmt(f, "[%d=%d]", t->fd0, t->fd1);		pfmt(f, "%t", c1);		break;			}}  char*labelname(tree *t){	if(t==0)		return "";	switch(t->type){	default:	return "bad val";	case '$':	return "$";	case '"':	return "\"";	case '&':	return "&";	case '^':	return "^";	case '`':	return "`";	case ANDAND: return "&&";	case BANG:	return "!";	case BRACE:	return "{}";	case COUNT:	return "#";	case FN:		return "fn";	case IF:		return "if";	case NOT:		return "if not";	case OROR:	return "||";	case PCMD:	case PAREN:	return "()";	case SUB:		return "$()";	case SIMPLE:	return "cmd";	case SUBSHELL:	return "@";	case SWITCH:	return "switch";	case TWIDDLE:	return "~";	case WHILE:	return "while";	case ARGLIST:			return "arglist";	case ';':			return ";";	case WORDS:	return "words";	case FOR:		return "for";	case WORD:	return t->str;	case DUP:		return "dup";	case PIPEFD:	case REDIR:		switch(t->rtype){		case HERE:			return "<<!";		case READ:		case RDWR:			return "<";		case APPEND:			return ">>";		case WRITE:			return ">";		}	case '=':		return "=";	case PIPE:		return "|";	case FANIN:	return ">|";			case FANOUT:	return "|<";		}	return "poop";} char c = 'a';int n; char*newnode(void){	if(c == 'z'){		c = 'a';		n++;	}	return smprint("%c%d", c++, n);	}  voidleaf2node(io *f, tree *t, char *p){	char *n, *l;	if(t == nil)		return;	l = labelname(t);	n = newnode();	fprint(2, "\t%s [label=\"%s\"]\n", n, l);	if(p != nil)		fprint(2, "\t%s->%s\n", p, n);	leaf2node(f, c0, n);	leaf2node(f, c1, n);	leaf2node(f, c2, n);	free(n);} // XXX: fix this to work with rc's io systemvoidtree2dot(io *f, tree *t){	fprint(2, "digraph rc {\n");	leaf2node(f, t, nil);	fprint(2, "}\n");	}