xref: /original-bsd/usr.bin/struct/beautify/tree.c (revision 883fb6be)
1 #ifndef lint
2 static char sccsid[] = "@(#)tree.c	4.2	(Berkeley)	03/24/87";
3 #endif not lint
4 
5 # include "y.tab.h"
6 #include "b.h"
7 #include <stdio.h>
8 
9 
10 addroot(string,type,n1,n2)
11 char *string;
12 int type;
13 struct node *n1, *n2;
14 	{
15 	struct node *p;
16 	p = malloc(sizeof(*p));
17 	p->left = n1;
18 	p->right = n2;
19 	p->op = type;
20 	p->lit = malloc(slength(string) + 1);
21 	str_copy(string,p->lit,slength(string) + 1);
22 	return(p);
23 	}
24 
25 
26 freetree(tree)
27 struct node *tree;
28 	{
29 	if (tree)
30 		{freetree(tree->left);
31 		freetree(tree->right);
32 		freenode(tree);
33 		}
34 	}
35 
36 freenode(treenode)
37 struct node *treenode;
38 	{
39 	free(treenode->lit);
40 	free(treenode);
41 	}
42 
43 int compop[] =	{	'&',	'|',	'<',	'>',	xxeq,	xxle,	xxne,	xxge};
44 int notop[] =	{	'|',	'&',	xxge,	xxle,	xxne,	'>',	xxeq,	'<'};
45 char *opstring[] =	{ "||",  "&&",	">=",	"<=", "!=",	">",	"==",	"<"};
46 
47 checkneg(tree,neg)		/* eliminate nots if possible */
48 struct node *tree;
49 int neg;
50 	{
51 	int i;
52 	struct node *t;
53 	if (!tree) return(0);
54 	for (i =  0; i < 8; ++i)
55 		if (tree->op == compop[i]) break;
56 	if (i > 1 && i <  8 && tree ->left ->op == '-' && str_eq(tree->right->lit,"0"))
57 		{
58 		t = tree->right;
59 		tree->right = tree->left->right;
60 		freenode(t);
61 		t = tree->left;
62 		tree->left = tree->left->left;
63 		freenode(t);
64 		}
65 
66 
67 	if (neg)
68 		{
69 		if (tree ->op == '!')
70 			{
71 			t = tree->left;
72 			freenode(tree);
73 			return(checkneg(t,0));
74 			}
75 			if (i < 8)
76 				{
77 				tree->op = notop[i];
78 				free(tree->lit);
79 				tree->lit = malloc(slength(opstring[i])+1);
80 				str_copy(opstring[i],tree->lit, slength(opstring[i])+1);
81 				if (tree->op == '&' || tree->op == '|')
82 					{
83 					tree->left = checkneg(tree->left,1);
84 					tree->right = checkneg(tree->right,1);
85 					}
86 				return(tree);
87 				}
88 		if (tree->op == xxident && str_eq(tree->lit,".false."))
89 			str_copy(".true.",tree->lit, slength(".true.")+1);
90 		else if (tree->op == xxident && str_eq(tree->lit,".true."))
91 			{
92 			free(tree->lit);
93 			tree->lit = malloc(slength(".false.")+1);
94 			str_copy(".false.",tree->lit, slength(".false.")+1);
95 			}
96 		else
97 			{
98 			tree = addroot("!",'!',tree,0);
99 			tree->lit = malloc(2);
100 			str_copy("!",tree->lit, slength("!")+1);
101 			}
102 		return(tree);
103 		}
104 	else
105 		if (tree->op == '!')
106 			{
107 			t = tree;
108 			tree = tree->left;
109 			freenode(t);
110 			return(checkneg(tree,1));
111 			}
112 	else
113 		{tree->left = checkneg(tree->left,0);
114 		tree->right = checkneg(tree->right,0);
115 		return(tree);
116 		}
117 	}
118 
119 yield(tree,fprec)
120 struct node *tree;
121 int fprec;				/* fprec is precedence of father of this node */
122 	{
123 	int paren,p;
124 	static int oplast;			/* oplast = 1 iff last char printed was operator */
125 	if (!tree) return;
126 	p = prec(tree ->op);
127 	paren = (p < fprec || (oplast && tree->op == xxuminus)) ? 1 : 0;
128 
129 	if (paren)
130 		{
131 		putout('(',"(");
132 		oplast = 0;
133 		}
134 
135 	switch(tree->op)
136 		{
137 		case xxuminus:
138 			tree->op = '-';
139 		case '!':
140 			putout(tree->op,tree->lit);
141 			oplast = 1;
142 			yield(tree->left,p);
143 			break;
144 		case '&':
145 		case '|':
146 		case '<':
147 		case '>':
148 		case xxeq:
149 		case xxle:
150 		case xxge:
151 		case '+':
152 		case '-':
153 		case '*':
154 		case '/':
155 		case '^':
156 			yield(tree->left,p);
157 			putout(tree->op, tree->lit);
158 			oplast = 1;
159 			yield(tree->right,p);
160 			break;
161 		case xxidpar:
162 			yield(tree->left,0);
163 			putout('(',"(");
164 			oplast = 0;
165 			yield(tree->right,0);
166 			putout('(',")");
167 			oplast = 0;
168 			break;
169 		default:
170 			yield(tree->left,p);
171 			putout(tree->op, tree->lit);
172 			oplast = 0;
173 			yield(tree->right,p);
174 			break;
175 		}
176 	if (paren)
177 		{
178 		putout(')',")");
179 		oplast = 0;
180 		}
181 	}
182 
183 puttree(tree)
184 struct node *tree;
185 	{
186 	yield(tree,0);
187 	freetree(tree);
188 	}
189 
190 
191 prec(oper)
192 int oper;
193 	{
194 	switch(oper)
195 		{
196 		case ',':		return(0);
197 		case '|':	return(1);
198 		case '&':	return(2);
199 		case '!':	return(3);
200 
201 		case '<':		case '>':		case xxeq:
202 		case xxne:	case xxle:	case xxge:
203 				return(4);
204 		case '+':
205 	case '-':		return(5);
206 		case '*':
207 	case '/':		return(6);
208 		case xxuminus:	return(7);
209 		case '^':	return(8);
210 		default:	return(9);
211 		}
212 	}
213 str_copy(s,ptr,length)	/* copy s at ptr, return length of s */
214 char *s, *ptr;
215 int length;
216 	{int i;
217 	for (i = 0; i < length; i++)
218 		{
219 		ptr[i] = s[i];
220 		if (ptr[i] == '\0')
221 			return(i + 1);
222 		}
223 	fprintf(2,"string %s too long to be copied by str_copy at address %d\n",
224 			*s,ptr);
225 	exit(1);
226 	}
227 str_eq(s,t)
228 char s[],t[];
229 	{int j;
230 	for (j = 0; s[j] == t[j]; j++)
231 		{if (s[j] == '\0') return(1);}
232 	return(0);
233 	}
234 
235 slength(s)			/* return number of chars in s, not counting '\0' */
236 char *s;
237 	{
238 	int i;
239 	if (!s) return(-1);
240 	for (i = 0; s[i] != '\0'; i++);
241 	return(i);
242 	}
243