129 |
|
} |
130 |
|
|
131 |
|
|
132 |
+ |
epcmp(ep1, ep2) /* compare two expressions for equivalence */ |
133 |
+ |
register EPNODE *ep1, *ep2; |
134 |
+ |
{ |
135 |
+ |
double d; |
136 |
+ |
|
137 |
+ |
if (ep1->type != ep2->type) |
138 |
+ |
return(1); |
139 |
+ |
|
140 |
+ |
switch (ep1->type) { |
141 |
+ |
|
142 |
+ |
case VAR: |
143 |
+ |
return(ep1->v.ln != ep2->v.ln); |
144 |
+ |
|
145 |
+ |
case NUM: |
146 |
+ |
if (ep2->v.num == 0) |
147 |
+ |
return(ep1->v.num != 0); |
148 |
+ |
d = ep1->v.num / ep2->v.num; |
149 |
+ |
return(d > 1.000000000001 | d < 0.999999999999); |
150 |
+ |
|
151 |
+ |
case CHAN: |
152 |
+ |
case ARG: |
153 |
+ |
return(ep1->v.chan != ep2->v.chan); |
154 |
+ |
|
155 |
+ |
case '=': |
156 |
+ |
case ':': |
157 |
+ |
return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling)); |
158 |
+ |
|
159 |
+ |
case TICK: |
160 |
+ |
case SYM: /* should never get this one */ |
161 |
+ |
return(0); |
162 |
+ |
|
163 |
+ |
default: |
164 |
+ |
ep1 = ep1->v.kid; |
165 |
+ |
ep2 = ep2->v.kid; |
166 |
+ |
while (ep1 != NULL) { |
167 |
+ |
if (ep2 == NULL) |
168 |
+ |
return(1); |
169 |
+ |
if (epcmp(ep1, ep2)) |
170 |
+ |
return(1); |
171 |
+ |
ep1 = ep1->sibling; |
172 |
+ |
ep2 = ep2->sibling; |
173 |
+ |
} |
174 |
+ |
return(ep2 != NULL); |
175 |
+ |
} |
176 |
+ |
} |
177 |
+ |
|
178 |
+ |
|
179 |
|
epfree(epar) /* free a parse tree */ |
180 |
|
register EPNODE *epar; |
181 |
|
{ |