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