1277177Srrs/*-
2277177Srrs * Copyright (c) 2015 Netflix Inc.
3277177Srrs * All rights reserved.
4277177Srrs *
5277177Srrs * Redistribution and use in source and binary forms, with or without
6277177Srrs * modification, are permitted provided that the following conditions
7277177Srrs * are met:
8277177Srrs * 1. Redistributions of source code must retain the above copyright
9277177Srrs *    notice, this list of conditions and the following disclaimer,
10277177Srrs *    in this position and unchanged.
11277177Srrs * 2. Redistributions in binary form must reproduce the above copyright
12277177Srrs *    notice, this list of conditions and the following disclaimer in the
13277177Srrs *    documentation and/or other materials provided with the distribution.
14277177Srrs * 3. The name of the author may not be used to endorse or promote products
15277177Srrs *    derived from this software without specific prior written permission
16277177Srrs *
17277177Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18277177Srrs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19277177Srrs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20277177Srrs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21277177Srrs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22277177Srrs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23277177Srrs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24277177Srrs * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25277177Srrs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26277177Srrs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27277177Srrs */
28277177Srrs#include <sys/types.h>
29277177Srrs#include <stdio.h>
30277177Srrs#include <stdlib.h>
31277177Srrs#include <unistd.h>
32277177Srrs#include <string.h>
33277177Srrs#include <strings.h>
34277177Srrs#include <ctype.h>
35277177Srrs#include "eval_expr.h"
36277177Srrs__FBSDID("$FreeBSD: releng/11.0/usr.sbin/pmcstudy/eval_expr.c 289677 2015-10-21 05:37:09Z eadler $");
37277177Srrs
38277177Srrsstatic struct expression *
39277177Srrsalloc_and_hook_expr(struct expression **exp_p, struct expression **last_p)
40277177Srrs{
41277177Srrs	struct expression *ex, *at;
42277177Srrs
43277177Srrs	ex = malloc(sizeof(struct expression));
44277177Srrs	if (ex == NULL) {
45277177Srrs		printf("Out of memory in exp allocation\n");
46277177Srrs		exit(-2);
47277177Srrs	}
48277177Srrs	memset(ex, 0, sizeof(struct expression));
49277177Srrs	if (*exp_p == NULL) {
50277177Srrs		*exp_p = ex;
51277177Srrs	}
52277177Srrs	at = *last_p;
53277177Srrs	if (at == NULL) {
54277177Srrs		/* First one, its last */
55277177Srrs		*last_p = ex;
56277177Srrs	} else {
57277177Srrs		/* Chain it to the end and update last */
58277177Srrs		at->next = ex;
59277177Srrs		ex->prev = at;
60277177Srrs		*last_p = ex;
61277177Srrs	}
62277177Srrs	return (ex);
63277177Srrs}
64277177Srrs
65277177Srrs
66277177Srrsstatic int
67277177Srrsvalidate_expr(struct expression *exp, int val1_is_set, int op_is_set, int val2_is_set,
68277177Srrs	      int *op_cnt)
69277177Srrs{
70277177Srrs	int val1, op, val2;
71277177Srrs	int open_cnt;
72277177Srrs	val1 = op = val2 = 0;
73277177Srrs	if (val1_is_set) {
74277177Srrs		val1 = 1;
75277177Srrs	}
76277177Srrs	if (op_is_set) {
77277177Srrs		op = 1;
78277177Srrs	}
79277177Srrs	if (val2_is_set) {
80277177Srrs		val2 = 1;
81277177Srrs	}
82277177Srrs	open_cnt = *op_cnt;
83277177Srrs	if (exp == NULL) {
84277177Srrs		/* End of the road */
85277177Srrs		if (val1 && op && val2 && (open_cnt == 0)) {
86277177Srrs			return(0);
87277177Srrs		} else {
88277177Srrs			return(1);
89277177Srrs		}
90277177Srrs	}
91277177Srrs	switch(exp->type) {
92277177Srrs	case TYPE_OP_PLUS:
93277177Srrs	case TYPE_OP_MINUS:
94277177Srrs	case TYPE_OP_MULT:
95277177Srrs	case TYPE_OP_DIVIDE:
96277177Srrs		if (val1 && op && val2) {
97277177Srrs			/* We are at x + y +
98277177Srrs			 * collapse back to val/op
99277177Srrs			 */
100277177Srrs			val1 = 1;
101277177Srrs			op = 1;
102277177Srrs			val2 = 0;
103277177Srrs		} else if ((op == 0) && (val1)) {
104277177Srrs			op = 1;
105277177Srrs		} else {
106277177Srrs			printf("Op but no val1 set\n");
107277177Srrs			return(-1);
108277177Srrs		}
109277177Srrs		break;
110277177Srrs	case TYPE_PARN_OPEN:
111277177Srrs		if (exp->next == NULL) {
112277177Srrs			printf("NULL after open paren\n");
113277177Srrs			exit(-1);
114277177Srrs		}
115277177Srrs		if ((exp->next->type == TYPE_OP_PLUS) ||
116277177Srrs		    (exp->next->type == TYPE_OP_MINUS) ||
117277177Srrs		    (exp->next->type == TYPE_OP_DIVIDE) ||
118277177Srrs		    (exp->next->type == TYPE_OP_MULT)) {
119277177Srrs			printf("'( OP' -- not allowed\n");
120277177Srrs			return(-1);
121277177Srrs		}
122277177Srrs		if (val1 && (op == 0)) {
123277177Srrs			printf("'Val (' -- not allowed\n");
124277177Srrs			return(-1);
125277177Srrs		}
126277177Srrs		if (val1 && op && val2) {
127277177Srrs			printf("'Val OP Val (' -- not allowed\n");
128277177Srrs			return(-1);
129277177Srrs		}
130277177Srrs		open_cnt++;
131277177Srrs		*op_cnt = open_cnt;
132277177Srrs		if (val1) {
133277177Srrs			if (validate_expr(exp->next, 0, 0, 0, op_cnt) == 0) {
134277177Srrs				val2 = 1;
135277177Srrs			} else {
136277177Srrs				return(-1);
137277177Srrs			}
138277177Srrs		} else {
139277177Srrs			return(validate_expr(exp->next, 0, 0, 0, op_cnt));
140277177Srrs		}
141277177Srrs		break;
142277177Srrs	case TYPE_PARN_CLOSE:
143277177Srrs		open_cnt--;
144277177Srrs		*op_cnt = open_cnt;
145277177Srrs		if (val1 && op && val2) {
146277177Srrs			return(0);
147277177Srrs		} else {
148277177Srrs			printf("Found close paren and not complete\n");
149277177Srrs			return(-1);
150277177Srrs		}
151277177Srrs		break;
152277177Srrs	case TYPE_VALUE_CON:
153277177Srrs	case TYPE_VALUE_PMC:
154277177Srrs		if (val1 == 0) {
155277177Srrs			val1 = 1;
156277177Srrs		} else if (val1 && op) {
157277177Srrs			val2 = 1;
158277177Srrs		} else {
159277177Srrs			printf("val1 set, val2 about to be set op empty\n");
160277177Srrs			return(-1);
161277177Srrs		}
162277177Srrs		break;
163277177Srrs	default:
164277177Srrs		printf("unknown type %d\n", exp->type);
165277177Srrs		exit(-5);
166277177Srrs		break;
167277177Srrs	}
168277177Srrs	return(validate_expr(exp->next, val1, op, val2, op_cnt));
169277177Srrs}
170277177Srrs
171277177Srrsvoid
172277177Srrsprint_exp(struct expression *exp)
173277177Srrs{
174277177Srrs	if (exp == NULL) {
175277177Srrs		printf("\n");
176277177Srrs		return;
177277177Srrs	}
178277177Srrs	switch(exp->type) {
179277177Srrs	case TYPE_OP_PLUS:
180277177Srrs		printf(" + ");
181277177Srrs		break;
182277177Srrs	case TYPE_OP_MINUS:
183277177Srrs		printf(" - ");
184277177Srrs		break;
185277177Srrs	case TYPE_OP_MULT:
186277177Srrs		printf(" * ");
187277177Srrs		break;
188277177Srrs	case TYPE_OP_DIVIDE:
189277177Srrs		printf(" / ");
190277177Srrs		break;
191277177Srrs	case TYPE_PARN_OPEN:
192277177Srrs		printf(" ( ");
193277177Srrs		break;
194277177Srrs	case TYPE_PARN_CLOSE:
195277177Srrs		printf(" ) ");
196277177Srrs		break;
197277177Srrs	case TYPE_VALUE_CON:
198277177Srrs		printf("%f", exp->value);
199277177Srrs		break;
200277177Srrs	case TYPE_VALUE_PMC:
201277177Srrs		printf("%s", exp->name);
202277177Srrs		break;
203277177Srrs	default:
204277177Srrs		printf("Unknown op %d\n", exp->type);
205277177Srrs		break;
206277177Srrs	}
207277177Srrs	print_exp(exp->next);
208277177Srrs}
209277177Srrs
210277177Srrsstatic void
211277177Srrswalk_back_and_insert_paren(struct expression **beg, struct expression *frm)
212277177Srrs{
213277177Srrs	struct expression *at, *ex;
214277177Srrs
215277177Srrs	/* Setup our new open paren */
216277177Srrs	ex = malloc(sizeof(struct expression));
217277177Srrs	if (ex == NULL) {
218277177Srrs		printf("Out of memory in exp allocation\n");
219277177Srrs		exit(-2);
220277177Srrs	}
221277177Srrs	memset(ex, 0, sizeof(struct expression));
222277177Srrs	ex->type = TYPE_PARN_OPEN;
223277177Srrs	/* Now lets place it */
224277177Srrs	at = frm->prev;
225277177Srrs	if (at == *beg) {
226277177Srrs		/* We are inserting at the head of the list */
227277177Srrs	in_beg:
228277177Srrs		ex->next = at;
229277177Srrs		at->prev = ex;
230277177Srrs		*beg = ex;
231277177Srrs		return;
232277177Srrs	} else if ((at->type == TYPE_VALUE_CON) ||
233277177Srrs	    (at->type == TYPE_VALUE_PMC)) {
234277177Srrs		/* Simple case we have a value in the previous position */
235277177Srrs	in_mid:
236277177Srrs		ex->prev = at->prev;
237277177Srrs		ex->prev->next = ex;
238277177Srrs		ex->next = at;
239277177Srrs		at->prev = ex;
240277177Srrs		return;
241277177Srrs	} else if (at->type == TYPE_PARN_CLOSE) {
242277177Srrs		/* Skip through until we reach beg or all ( closes */
243277177Srrs		int par_cnt=1;
244277177Srrs
245277177Srrs		at = at->prev;
246277177Srrs		while(par_cnt) {
247277177Srrs			if (at->type == TYPE_PARN_CLOSE) {
248277177Srrs				par_cnt++;
249277177Srrs			} else if (at->type == TYPE_PARN_OPEN) {
250277177Srrs				par_cnt--;
251277177Srrs				if (par_cnt == 0) {
252277177Srrs					break;
253277177Srrs				}
254277177Srrs			}
255277177Srrs			at = at->prev;
256277177Srrs		}
257277177Srrs		if (at == *beg) {
258277177Srrs			/* At beginning we insert */
259277177Srrs			goto in_beg;
260277177Srrs		} else {
261277177Srrs			goto in_mid;
262277177Srrs		}
263277177Srrs	} else {
264277177Srrs		printf("%s:Unexpected type:%d?\n",
265277177Srrs		       __FUNCTION__, at->type);
266277177Srrs		exit(-1);
267277177Srrs	}
268277177Srrs}
269277177Srrs
270277177Srrsstatic void
271277177Srrswalk_fwd_and_insert_paren(struct expression *frm, struct expression **added)
272277177Srrs{
273277177Srrs	struct expression *at, *ex;
274277177Srrs	/* Setup our new close paren */
275277177Srrs	ex = malloc(sizeof(struct expression));
276277177Srrs	if (ex == NULL) {
277277177Srrs		printf("Out of memory in exp allocation\n");
278277177Srrs		exit(-2);
279277177Srrs	}
280277177Srrs	memset(ex, 0, sizeof(struct expression));
281277177Srrs	ex->type = TYPE_PARN_CLOSE;
282277177Srrs	*added = ex;
283277177Srrs	/* Now lets place it */
284277177Srrs	at = frm->next;
285277177Srrs	if ((at->type == TYPE_VALUE_CON) ||
286277177Srrs	    (at->type == TYPE_VALUE_PMC)) {
287277177Srrs		/* Simple case we have a value in the previous position */
288277177Srrs	insertit:
289277177Srrs		ex->next = at->next;
290277177Srrs		ex->prev = at;
291277177Srrs		at->next = ex;
292277177Srrs		return;
293277177Srrs	} else if (at->type == TYPE_PARN_OPEN) {
294277177Srrs		int par_cnt=1;
295277177Srrs		at = at->next;
296277177Srrs		while(par_cnt) {
297277177Srrs			if (at->type == TYPE_PARN_OPEN) {
298277177Srrs				par_cnt++;
299277177Srrs			} else if (at->type == TYPE_PARN_CLOSE) {
300277177Srrs				par_cnt--;
301277177Srrs				if (par_cnt == 0) {
302277177Srrs					break;
303277177Srrs				}
304277177Srrs			}
305277177Srrs			at = at->next;
306277177Srrs		}
307277177Srrs		goto insertit;
308277177Srrs	} else {
309277177Srrs		printf("%s:Unexpected type:%d?\n",
310277177Srrs		       __FUNCTION__,
311277177Srrs		       at->type);
312277177Srrs		exit(-1);
313277177Srrs	}
314277177Srrs}
315277177Srrs
316277177Srrs
317277177Srrsstatic void
318277177Srrsadd_precendence(struct expression **beg, struct expression *start, struct expression *end)
319277177Srrs{
320277177Srrs	/*
321277177Srrs	 * Between start and end add () around any * or /. This
322277177Srrs	 * is quite tricky since if there is a () set inside the
323277177Srrs	 * list we need to skip over everything in the ()'s considering
324277177Srrs	 * that just a value.
325277177Srrs	 */
326277177Srrs	struct expression *at, *newone;
327277177Srrs	int open_cnt;
328277177Srrs
329277177Srrs	at = start;
330277177Srrs	open_cnt = 0;
331277177Srrs	while(at != end) {
332277177Srrs		if (at->type == TYPE_PARN_OPEN) {
333277177Srrs			open_cnt++;
334277177Srrs		}
335277177Srrs		if (at->type == TYPE_PARN_CLOSE) {
336277177Srrs			open_cnt--;
337277177Srrs		}
338277177Srrs		if (open_cnt == 0) {
339277177Srrs			if ((at->type == TYPE_OP_MULT) ||
340277177Srrs			    (at->type == TYPE_OP_DIVIDE)) {
341277177Srrs				walk_back_and_insert_paren(beg, at);
342277177Srrs				walk_fwd_and_insert_paren(at, &newone);
343277177Srrs				at = newone->next;
344277177Srrs				continue;
345277177Srrs			}
346277177Srrs		}
347277177Srrs		at = at->next;
348277177Srrs	}
349277177Srrs
350277177Srrs}
351277177Srrs
352277177Srrsstatic void
353277177Srrsset_math_precidence(struct expression **beg, struct expression *exp, struct expression **stopped)
354277177Srrs{
355277177Srrs	struct expression *at, *start, *end;
356277177Srrs	int cnt_lower, cnt_upper;
357277177Srrs	/*
358277177Srrs	 * Walk through and set any math precedence to
359277177Srrs	 * get proper precedence we insert () around * / over + -
360277177Srrs	 */
361277177Srrs	end = NULL;
362277177Srrs	start = at = exp;
363277177Srrs	cnt_lower = cnt_upper = 0;
364277177Srrs	while(at) {
365277177Srrs		if (at->type == TYPE_PARN_CLOSE) {
366277177Srrs			/* Done with that paren */
367277177Srrs			if (stopped) {
368277177Srrs				*stopped = at;
369277177Srrs			}
370277177Srrs			if (cnt_lower && cnt_upper) {
371277177Srrs				/* We have a mixed set ... add precedence between start/end */
372277177Srrs				add_precendence(beg, start, end);
373277177Srrs			}
374277177Srrs			return;
375277177Srrs		}
376277177Srrs		if (at->type == TYPE_PARN_OPEN) {
377277177Srrs			set_math_precidence(beg, at->next, &end);
378277177Srrs			at = end;
379277177Srrs			continue;
380277177Srrs		} else if ((at->type == TYPE_OP_PLUS) ||
381277177Srrs			   (at->type == TYPE_OP_MINUS)) {
382277177Srrs			cnt_lower++;
383277177Srrs		} else if ((at->type == TYPE_OP_DIVIDE) ||
384277177Srrs			   (at->type == TYPE_OP_MULT)) {
385277177Srrs			cnt_upper++;
386277177Srrs		}
387277177Srrs		at = at->next;
388277177Srrs	}
389277177Srrs	if (cnt_lower && cnt_upper) {
390277177Srrs		add_precendence(beg, start, NULL);
391277177Srrs	}
392277177Srrs}
393277177Srrs
394277177Srrsextern char **valid_pmcs;
395277177Srrsextern int valid_pmc_cnt;
396277177Srrs
397277177Srrsstatic void
398277177Srrspmc_name_set(struct expression *at)
399277177Srrs{
400277177Srrs	int i, idx, fnd;
401277177Srrs
402277177Srrs	if (at->name[0] == '%') {
403277177Srrs		/* Special number after $ gives index */
404277177Srrs		idx = strtol(&at->name[1], NULL, 0);
405277177Srrs		if (idx >= valid_pmc_cnt) {
406277177Srrs			printf("Unknown PMC %s -- largest we have is $%d -- can't run your expression\n",
407277177Srrs			       at->name, valid_pmc_cnt);
408277177Srrs			exit(-1);
409277177Srrs		}
410277177Srrs		strcpy(at->name, valid_pmcs[idx]);
411277177Srrs	} else {
412277177Srrs		for(i=0, fnd=0; i<valid_pmc_cnt; i++) {
413277177Srrs			if (strcmp(valid_pmcs[i], at->name) == 0) {
414277177Srrs				fnd = 1;
415277177Srrs				break;
416277177Srrs			}
417277177Srrs		}
418277177Srrs		if (!fnd) {
419277177Srrs			printf("PMC %s does not exist on this machine -- can't run your expression\n",
420277177Srrs			       at->name);
421277177Srrs			exit(-1);
422277177Srrs		}
423277177Srrs	}
424277177Srrs}
425277177Srrs
426277177Srrsstruct expression *
427277177Srrsparse_expression(char *str)
428277177Srrs{
429277177Srrs	struct expression *exp=NULL, *last=NULL, *at;
430277177Srrs	int open_par, close_par;
431277177Srrs	int op_cnt=0;
432277177Srrs	size_t siz, i, x;
433277177Srrs	/*
434277177Srrs	 * Walk through a string expression and convert
435277177Srrs	 * it to a linked list of actions. We do this by:
436277177Srrs	 * a) Counting the open/close paren's, there must
437277177Srrs	 *    be a matching number.
438277177Srrs	 * b) If we have balanced paren's then create a linked list
439277177Srrs	 *    of the operators, then we validate that expression further.
440277177Srrs	 * c) Validating that we have:
441277177Srrs	 *      val OP val <or>
442277177Srrs	 *      val OP (  <and>
443277177Srrs	 *    inside every paran you have a:
444277177Srrs	 *      val OP val <or>
445277177Srrs	 *      val OP (   <recursively>
446277177Srrs	 * d) A final optional step (not implemented yet) would be
447289677Seadler	 *    to insert the mathematical precedence paran's. For
448277177Srrs	 *    the start we will just do the left to right evaluation and
449277177Srrs	 *    then later we can add this guy to add paran's to make it
450277177Srrs	 *    mathimatically correct... i.e instead of 1 + 2 * 3 we
451277177Srrs	 *    would translate it into 1 + ( 2 * 3).
452277177Srrs	 */
453277177Srrs	open_par = close_par = 0;
454277177Srrs	siz = strlen(str);
455277177Srrs	/* No trailing newline please */
456277177Srrs	if (str[(siz-1)] == '\n') {
457277177Srrs		str[(siz-1)] = 0;
458277177Srrs		siz--;
459277177Srrs	}
460277177Srrs	for(i=0; i<siz; i++) {
461277177Srrs		if (str[i] == '(') {
462277177Srrs			open_par++;
463277177Srrs		} else if (str[i] == ')') {
464277177Srrs			close_par++;
465277177Srrs		}
466277177Srrs	}
467277177Srrs	if (open_par != close_par) {
468277177Srrs		printf("Invalid expression '%s' %d open paren's and %d close?\n",
469277177Srrs		       str, open_par, close_par);
470277177Srrs		exit(-1);
471277177Srrs	}
472277177Srrs	for(i=0; i<siz; i++) {
473277177Srrs		if (str[i] == '(') {
474277177Srrs			at = alloc_and_hook_expr(&exp, &last);
475277177Srrs			at->type = TYPE_PARN_OPEN;
476277177Srrs		} else if (str[i] == ')') {
477277177Srrs			at = alloc_and_hook_expr(&exp, &last);
478277177Srrs			at->type = TYPE_PARN_CLOSE;
479277177Srrs		} else if (str[i] == ' ') {
480277177Srrs			/* Extra blank */
481277177Srrs			continue;
482277177Srrs		} else if (str[i] == '\t') {
483277177Srrs			/* Extra tab */
484277177Srrs			continue;
485277177Srrs		} else if (str[i] == '+') {
486277177Srrs			at = alloc_and_hook_expr(&exp, &last);
487277177Srrs			at->type = TYPE_OP_PLUS;
488277177Srrs		} else if (str[i] == '-') {
489277177Srrs			at = alloc_and_hook_expr(&exp, &last);
490277177Srrs			at->type = TYPE_OP_MINUS;
491277177Srrs		} else if (str[i] == '/') {
492277177Srrs			at = alloc_and_hook_expr(&exp, &last);
493277177Srrs			at->type = TYPE_OP_DIVIDE;
494277177Srrs		} else if (str[i] == '*') {
495277177Srrs			at = alloc_and_hook_expr(&exp, &last);
496277177Srrs			at->type = TYPE_OP_MULT;
497277177Srrs		} else {
498277177Srrs			/* Its a value or PMC constant */
499277177Srrs			at = alloc_and_hook_expr(&exp, &last);
500277177Srrs			if (isdigit(str[i]) || (str[i] == '.')) {
501277177Srrs				at->type = TYPE_VALUE_CON;
502277177Srrs			} else {
503277177Srrs				at->type = TYPE_VALUE_PMC;
504277177Srrs			}
505277177Srrs			x = 0;
506277177Srrs			while ((str[i] != ' ') &&
507277177Srrs			       (str[i] != '\t') &&
508277177Srrs			       (str[i] != 0) &&
509277177Srrs			       (str[i] != ')') &&
510277177Srrs			       (str[i] != '(')) {
511277177Srrs				/* We collect the constant until a space or tab */
512277177Srrs				at->name[x] = str[i];
513277177Srrs				i++;
514277177Srrs				x++;
515277177Srrs				if (x >=(sizeof(at->name)-1)) {
516277177Srrs					printf("Value/Constant too long %d max:%d\n",
517277177Srrs					       (int)x, (int)(sizeof(at->name)-1));
518277177Srrs					exit(-3);
519277177Srrs				}
520277177Srrs			}
521277177Srrs			if (str[i] != 0) {
522277177Srrs				/* Need to back up and see the last char since
523277177Srrs				 * the for will increment the loop.
524277177Srrs				 */
525277177Srrs				i--;
526277177Srrs			}
527277177Srrs			/* Now we have pulled the string, set it up */
528277177Srrs			if (at->type == TYPE_VALUE_CON) {
529277177Srrs				at->state = STATE_FILLED;
530277177Srrs				at->value = strtod(at->name, NULL);
531277177Srrs			} else {
532277177Srrs				pmc_name_set(at);
533277177Srrs			}
534277177Srrs		}
535277177Srrs	}
536277177Srrs	/* Now lets validate its a workable expression */
537277177Srrs	if (validate_expr(exp, 0, 0, 0, &op_cnt)) {
538277177Srrs		printf("Invalid expression\n");
539277177Srrs		exit(-4);
540277177Srrs	}
541277177Srrs	set_math_precidence(&exp, exp, NULL);
542277177Srrs	return (exp);
543277177Srrs}
544277177Srrs
545277177Srrs
546277177Srrs
547277177Srrsstatic struct expression *
548277177Srrsgather_exp_to_paren_close(struct expression *exp, double *val_fill)
549277177Srrs{
550277177Srrs	/*
551277177Srrs	 * I have been given ( ???
552277177Srrs	 * so I could see either
553277177Srrs	 * (
554277177Srrs	 * or
555277177Srrs	 * Val Op
556277177Srrs	 *
557277177Srrs	 */
558277177Srrs	struct expression *lastproc;
559277177Srrs	double val;
560277177Srrs
561277177Srrs	if (exp->type == TYPE_PARN_OPEN) {
562277177Srrs		lastproc = gather_exp_to_paren_close(exp->next, &val);
563277177Srrs		*val_fill = val;
564277177Srrs	} else {
565277177Srrs		*val_fill = run_expr(exp, 0, &lastproc);
566277177Srrs	}
567277177Srrs	return(lastproc);
568277177Srrs}
569277177Srrs
570277177Srrs
571277177Srrsdouble
572277177Srrsrun_expr(struct expression *exp, int initial_call, struct expression **lastone)
573277177Srrs{
574277177Srrs	/*
575277177Srrs	 * We expect to find either
576277177Srrs	 * a) A Open Paren
577277177Srrs	 * or
578277177Srrs	 * b) Val-> Op -> Val
579277177Srrs	 * or
580277177Srrs	 * c) Val-> Op -> Open Paren
581277177Srrs	 */
582277177Srrs	double val1, val2, res;
583277177Srrs	struct expression *op, *other_half, *rest;
584277177Srrs
585277177Srrs	if (exp->type == TYPE_PARN_OPEN) {
586277177Srrs		op = gather_exp_to_paren_close(exp->next, &val1);
587277177Srrs	} else if(exp->type == TYPE_VALUE_CON) {
588277177Srrs		val1 = exp->value;
589277177Srrs		op = exp->next;
590277177Srrs	} else if (exp->type ==  TYPE_VALUE_PMC) {
591277177Srrs		val1 = exp->value;
592277177Srrs		op = exp->next;
593277177Srrs	} else {
594277177Srrs		printf("Illegal value in %s huh?\n", __FUNCTION__);
595277177Srrs		exit(-1);
596277177Srrs	}
597277177Srrs	if (op == NULL) {
598277177Srrs		return (val1);
599277177Srrs	}
600277177Srrsmore_to_do:
601277177Srrs	other_half = op->next;
602277177Srrs	if (other_half->type == TYPE_PARN_OPEN) {
603277177Srrs		rest = gather_exp_to_paren_close(other_half->next, &val2);
604277177Srrs	} else if(other_half->type == TYPE_VALUE_CON) {
605277177Srrs		val2 = other_half->value;
606277177Srrs		rest = other_half->next;
607277177Srrs	} else if (other_half->type ==  TYPE_VALUE_PMC) {
608277177Srrs		val2 = other_half->value;
609277177Srrs		rest = other_half->next;
610277177Srrs	} else {
611277177Srrs		printf("Illegal2 value in %s huh?\n", __FUNCTION__);
612277177Srrs		exit(-1);
613277177Srrs	}
614277177Srrs	switch(op->type) {
615277177Srrs	case TYPE_OP_PLUS:
616277177Srrs		res = val1 + val2;
617277177Srrs		break;
618277177Srrs	case TYPE_OP_MINUS:
619277177Srrs		res = val1 - val2;
620277177Srrs		break;
621277177Srrs	case TYPE_OP_MULT:
622277177Srrs		res = val1 * val2;
623277177Srrs		break;
624277177Srrs	case TYPE_OP_DIVIDE:
625277177Srrs		if (val2 != 0.0)
626277177Srrs			res = val1 / val2;
627277177Srrs		else {
628277177Srrs			printf("Division by zero averted\n");
629277177Srrs			res = 1.0;
630277177Srrs		}
631277177Srrs		break;
632277177Srrs	default:
633277177Srrs		printf("Op is not an operator -- its %d\n",
634277177Srrs		       op->type);
635277177Srrs		exit(-1);
636277177Srrs		break;
637277177Srrs	}
638277177Srrs	if (rest == NULL) {
639277177Srrs		if (lastone) {
640277177Srrs			*lastone = NULL;
641277177Srrs		}
642277177Srrs		return (res);
643277177Srrs	}
644277177Srrs	if ((rest->type == TYPE_PARN_CLOSE) && (initial_call == 0)) {
645277177Srrs		if (lastone) {
646277177Srrs			*lastone = rest->next;
647277177Srrs		}
648277177Srrs		return(res);
649277177Srrs	}
650277177Srrs	/* There is more, as in
651277177Srrs	 * a + b + c
652277177Srrs	 * where we just did a + b
653277177Srrs	 * so now it becomes val1 is set to res and
654277177Srrs	 * we need to proceed with the rest of it.
655277177Srrs	 */
656277177Srrs	val1 = res;
657277177Srrs	op = rest;
658277177Srrs	if ((op->type != TYPE_OP_PLUS) &&
659277177Srrs	    (op->type != TYPE_OP_MULT) &&
660277177Srrs	    (op->type != TYPE_OP_MINUS) &&
661277177Srrs	    (op->type != TYPE_OP_DIVIDE)) {
662277177Srrs		printf("%s ending on type:%d not an op??\n", __FUNCTION__, op->type);
663277177Srrs		return(res);
664277177Srrs	}
665277177Srrs	if (op)
666277177Srrs		goto more_to_do;
667277177Srrs	return (res);
668277177Srrs}
669277177Srrs
670277177Srrs#ifdef STAND_ALONE_TESTING
671277177Srrs
672277177Srrsstatic double
673277177Srrscalc_expr(struct expression *exp)
674277177Srrs{
675277177Srrs	struct expression *at;
676277177Srrs	double xx;
677277177Srrs
678277177Srrs	/* First clear PMC's setting */
679277177Srrs	for(at = exp; at != NULL; at = at->next) {
680277177Srrs		if (at->type == TYPE_VALUE_PMC) {
681277177Srrs			at->state = STATE_UNSET;
682277177Srrs		}
683277177Srrs	}
684277177Srrs	/* Now for all pmc's make up values .. here is where I would pull them */
685277177Srrs	for(at = exp; at != NULL; at = at->next) {
686277177Srrs		if (at->type == TYPE_VALUE_PMC) {
687277177Srrs			at->value = (random() * 1.0);
688277177Srrs			at->state = STATE_FILLED;
689277177Srrs			if (at->value == 0.0) {
690277177Srrs				/* So we don't have div by 0 */
691277177Srrs				at->value = 1.0;
692277177Srrs			}
693277177Srrs		}
694277177Srrs	}
695277177Srrs	/* Now lets calculate the expression */
696277177Srrs	print_exp(exp);
697277177Srrs	xx = run_expr(exp, 1, NULL);
698277177Srrs	printf("Answer is %f\n", xx);
699277177Srrs	return(xx);
700277177Srrs}
701277177Srrs
702277177Srrs
703277177Srrsint
704277177Srrsmain(int argc, char **argv)
705277177Srrs{
706277177Srrs	struct expression *exp;
707277177Srrs	if (argc < 2) {
708277177Srrs		printf("Use %s expression\n", argv[0]);
709277177Srrs		return(-1);
710277177Srrs	}
711277177Srrs	exp = parse_expression(argv[1]);
712277177Srrs	printf("Now the calc\n");
713277177Srrs	calc_expr(exp);
714277177Srrs	return(0);
715277177Srrs}
716277177Srrs
717277177Srrs#endif
718