[430] | 1 | #include "madx.h" |
---|
| 2 | |
---|
| 3 | static int |
---|
| 4 | is_operand(char c) { |
---|
| 5 | return (isalnum(c) || c == '_' || c == '.'); |
---|
| 6 | } |
---|
| 7 | |
---|
| 8 | static int |
---|
| 9 | is_operator(char c) { |
---|
| 10 | return strchr("-+*/^", c) != 0; |
---|
| 11 | } |
---|
| 12 | |
---|
| 13 | static int |
---|
| 14 | is_expr_start(char c) { |
---|
| 15 | return strchr("-+(",c) || is_operand(c); |
---|
| 16 | } |
---|
| 17 | |
---|
| 18 | #if 0 // not used... |
---|
| 19 | /* combine two parameters using compound expression */ |
---|
| 20 | static struct expression* |
---|
| 21 | comb_param(struct command_parameter* param1, char* op, struct command_parameter* param2) |
---|
| 22 | { |
---|
| 23 | return compound_expr(param1->expr,param1->double_value,op,param2->expr,param2->double_value); |
---|
| 24 | } |
---|
| 25 | #endif |
---|
| 26 | |
---|
| 27 | static double |
---|
| 28 | combine_expr_expr(struct expression* exp1, char* oper, |
---|
| 29 | struct expression* exp2, struct expression** comb_exp) |
---|
| 30 | { |
---|
| 31 | strcpy(c_dum->c, exp1->string); |
---|
| 32 | strcat(c_dum->c, oper); |
---|
| 33 | strcat(c_dum->c, exp2->string); |
---|
| 34 | mysplit(c_dum->c, tmp_p_array); |
---|
| 35 | *comb_exp = make_expression(tmp_p_array->curr, tmp_p_array->p); |
---|
| 36 | return expression_value(*comb_exp, 2); |
---|
| 37 | } |
---|
| 38 | |
---|
| 39 | static double |
---|
| 40 | combine_expr_val(struct expression* exp1, char* oper, double val2, struct expression** comb_exp) |
---|
| 41 | { |
---|
| 42 | strcpy(c_dum->c, exp1->string); |
---|
| 43 | sprintf(aux_buff->c, "%.12g", val2); |
---|
| 44 | strcat(c_dum->c, oper); |
---|
| 45 | strcat(c_dum->c, aux_buff->c); |
---|
| 46 | mysplit(c_dum->c, tmp_p_array); |
---|
| 47 | *comb_exp = make_expression(tmp_p_array->curr, tmp_p_array->p); |
---|
| 48 | return expression_value(*comb_exp, 2); |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | static double |
---|
| 52 | combine_val_expr(double val1, char* oper, struct expression* exp2, struct expression** comb_exp) |
---|
| 53 | { |
---|
| 54 | sprintf(c_dum->c, "%.12g", val1); |
---|
| 55 | strcat(c_dum->c, oper); |
---|
| 56 | strcat(c_dum->c, exp2->string); |
---|
| 57 | mysplit(c_dum->c, tmp_p_array); |
---|
| 58 | *comb_exp = make_expression(tmp_p_array->curr, tmp_p_array->p); |
---|
| 59 | return expression_value(*comb_exp, 2); |
---|
| 60 | } |
---|
| 61 | |
---|
| 62 | // public interface |
---|
| 63 | |
---|
| 64 | struct expression* |
---|
| 65 | make_expression(int n, char** toks) |
---|
| 66 | /* makes an expression from a list of tokens */ |
---|
| 67 | { |
---|
| 68 | struct expression* expr = NULL; |
---|
| 69 | |
---|
| 70 | if (polish_expr(n, toks) == 0) |
---|
| 71 | expr = new_expression(join_b(toks, n), deco); |
---|
| 72 | else warning("Invalid expression starting at:", join_b(toks, n)); |
---|
| 73 | return expr; |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | struct expression* |
---|
| 77 | new_expression(char* in_string, struct int_array* polish) |
---|
| 78 | { |
---|
| 79 | char rout_name[] = "new_expression"; |
---|
| 80 | int j; |
---|
| 81 | struct expression* ex = mycalloc(rout_name,1,sizeof(struct expression)); |
---|
| 82 | strcpy(ex->name, "expression"); |
---|
| 83 | ex->stamp = 123456; |
---|
| 84 | ex->string = mymalloc(rout_name,strlen(in_string)+1); |
---|
| 85 | strcpy(ex->string, in_string); |
---|
| 86 | if (watch_flag) fprintf(debug_file, "creating ++> %s\n", ex->name); |
---|
| 87 | if (polish != NULL) |
---|
| 88 | { |
---|
| 89 | ex->polish = new_int_array(polish->curr); |
---|
| 90 | ex->polish->curr = polish->curr; |
---|
| 91 | for (j = 0; j < polish->curr; j++) ex->polish->i[j] = polish->i[j]; |
---|
| 92 | } |
---|
| 93 | return ex; |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | struct expr_list* |
---|
| 97 | new_expr_list(int length) |
---|
| 98 | { |
---|
| 99 | char rout_name[] = "new_expr_list"; |
---|
| 100 | struct expr_list* ell = mycalloc(rout_name,1, sizeof(struct expr_list)); |
---|
| 101 | strcpy(ell->name, "expr_list"); |
---|
| 102 | ell->stamp = 123456; |
---|
| 103 | if (watch_flag) fprintf(debug_file, "creating ++> %s\n", ell->name); |
---|
| 104 | ell->list = |
---|
| 105 | (struct expression**) mycalloc(rout_name,length, sizeof(struct expression*)); |
---|
| 106 | ell->max = length; |
---|
| 107 | return ell; |
---|
| 108 | } |
---|
| 109 | |
---|
| 110 | double |
---|
| 111 | expression_value(struct expression* expr, int flag) /* recursive */ |
---|
| 112 | /* returns the value of an expression if valid, else zero */ |
---|
| 113 | { |
---|
| 114 | double val = zero; |
---|
| 115 | if (expr->status == 0 || flag == 2) |
---|
| 116 | { |
---|
| 117 | if (expr->polish != NULL) |
---|
| 118 | { |
---|
| 119 | val = expr->value = polish_value(expr->polish, expr->string); |
---|
| 120 | expr->status = 1; |
---|
| 121 | } |
---|
| 122 | } |
---|
| 123 | else val = expr->value; |
---|
| 124 | return val; |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | struct expression* |
---|
| 128 | clone_expression(struct expression* p) |
---|
| 129 | { |
---|
| 130 | struct expression* clone; |
---|
| 131 | if (p == NULL) return NULL; |
---|
| 132 | clone = new_expression(p->string, p->polish); |
---|
| 133 | clone->status = p->status; |
---|
| 134 | clone->value = p->value; |
---|
| 135 | return clone; |
---|
| 136 | } |
---|
| 137 | |
---|
| 138 | struct expr_list* |
---|
| 139 | clone_expr_list(struct expr_list* p) |
---|
| 140 | { |
---|
| 141 | int i; |
---|
| 142 | struct expr_list* clone; |
---|
| 143 | if (p == NULL) return NULL; |
---|
| 144 | clone = new_expr_list(p->curr); |
---|
| 145 | for (i = 0; i < p->curr; i++) clone->list[i] = clone_expression(p->list[i]); |
---|
| 146 | clone->curr = p->curr; |
---|
| 147 | return clone; |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | struct expression* |
---|
| 151 | delete_expression(struct expression* expr) |
---|
| 152 | { |
---|
| 153 | char rout_name[] = "delete_expression"; |
---|
| 154 | if (expr == NULL) return NULL; |
---|
| 155 | if (stamp_flag && expr->stamp != 123456) |
---|
| 156 | fprintf(stamp_file, "d_ex double delete --> %s\n", expr->name); |
---|
| 157 | if (watch_flag) fprintf(debug_file, "deleting --> %s\n", expr->name); |
---|
| 158 | if (expr->polish != NULL) expr->polish = delete_int_array(expr->polish); |
---|
| 159 | if (expr->string != NULL) myfree(rout_name, expr->string); |
---|
| 160 | myfree(rout_name, expr); |
---|
| 161 | return NULL; |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | struct expr_list* |
---|
| 165 | delete_expr_list(struct expr_list* exprl) |
---|
| 166 | { |
---|
| 167 | char rout_name[] = "delete_expr_list"; |
---|
| 168 | int i; |
---|
| 169 | if (exprl == NULL) return NULL; |
---|
| 170 | if (stamp_flag && exprl->stamp != 123456) |
---|
| 171 | fprintf(stamp_file, "d_ex_l double delete --> %s\n", exprl->name); |
---|
| 172 | if (watch_flag) fprintf(debug_file, "deleting --> %s\n", exprl->name); |
---|
| 173 | if (exprl->list != NULL) |
---|
| 174 | { |
---|
| 175 | for (i = 0; i < exprl->curr; i++) |
---|
| 176 | if (exprl->list[i] != NULL) delete_expression(exprl->list[i]); |
---|
| 177 | myfree(rout_name, exprl->list); |
---|
| 178 | } |
---|
| 179 | myfree(rout_name, exprl); |
---|
| 180 | return NULL; |
---|
| 181 | } |
---|
| 182 | |
---|
| 183 | void |
---|
| 184 | grow_expr_list(struct expr_list* p) |
---|
| 185 | { |
---|
| 186 | char rout_name[] = "grow_expr_list"; |
---|
| 187 | struct expression** e_loc = p->list; |
---|
| 188 | int j, new = 2*p->max; |
---|
| 189 | p->max = new; |
---|
| 190 | p->list = mycalloc(rout_name,new, sizeof(struct expression*)); |
---|
| 191 | for (j = 0; j < p->curr; j++) p->list[j] = e_loc[j]; |
---|
| 192 | myfree(rout_name, e_loc); |
---|
| 193 | } |
---|
| 194 | |
---|
| 195 | void |
---|
| 196 | dump_expression(struct expression* ex) |
---|
| 197 | { |
---|
| 198 | ex->value = expression_value(ex, 2); |
---|
| 199 | fprintf(prt_file, v_format("expression: %s :: value: %F\n"), |
---|
| 200 | ex->string, ex->value); |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | double |
---|
| 204 | expr_combine(struct expression* exp1, double val1, char* oper, |
---|
| 205 | struct expression* exp2, double val2, |
---|
| 206 | struct expression** exp_comb) |
---|
| 207 | { |
---|
| 208 | double val = 0; |
---|
| 209 | |
---|
| 210 | if (exp1 == NULL && exp2 == NULL) |
---|
| 211 | { |
---|
| 212 | *exp_comb = NULL; |
---|
| 213 | switch(oper[1]) |
---|
| 214 | { |
---|
| 215 | case '+': val = val1 + val2; break; |
---|
| 216 | case '-': val = val1 - val2; break; |
---|
| 217 | } |
---|
| 218 | } |
---|
| 219 | else if(exp1 == NULL) val = combine_val_expr (val1, oper, exp2, exp_comb); |
---|
| 220 | else if(exp2 == NULL) val = combine_expr_val (exp1, oper, val2, exp_comb); |
---|
| 221 | else val = combine_expr_expr(exp1, oper, exp2, exp_comb); |
---|
| 222 | return val; |
---|
| 223 | } |
---|
| 224 | |
---|
| 225 | void |
---|
| 226 | update_vector(struct expr_list* ell, struct double_array* da) |
---|
| 227 | { |
---|
| 228 | int i; |
---|
| 229 | for (i = 0; i < ell->curr; i++) |
---|
| 230 | { |
---|
| 231 | if (ell->list[i] != NULL) |
---|
| 232 | { |
---|
| 233 | while (da->max < i) grow_double_array(da); |
---|
| 234 | da->a[i] = expression_value(ell->list[i], 2); |
---|
| 235 | } |
---|
| 236 | } |
---|
| 237 | if (da->curr < ell->curr) da->curr = ell->curr; |
---|
| 238 | } |
---|
| 239 | |
---|
| 240 | void |
---|
| 241 | fill_expr_list(char** toks, int s_start, int s_end, struct expr_list* p) |
---|
| 242 | { |
---|
| 243 | int start = s_start, nitem = s_end + 1, end, cnt = 0, nc; |
---|
| 244 | while (start < nitem) |
---|
| 245 | { |
---|
| 246 | if ((nc = next_char(',', toks, start, nitem)) < 0) nc = nitem; |
---|
| 247 | if (loc_expr(toks, nc, start, &end)) |
---|
| 248 | { |
---|
| 249 | if (cnt == p->max) grow_expr_list(p); |
---|
| 250 | p->list[cnt++] = make_expression(end + 1 - start, &toks[start]); |
---|
| 251 | start = nc + 1; |
---|
| 252 | } |
---|
| 253 | else break; |
---|
| 254 | } |
---|
| 255 | p->curr = cnt; |
---|
| 256 | } |
---|
| 257 | |
---|
| 258 | void |
---|
| 259 | fill_expr_var_list(struct el_list* ell, struct expression* expr, struct var_list* varl) |
---|
| 260 | /* puts all variables an expression depends on, in a list */ |
---|
| 261 | { |
---|
| 262 | struct variable* var; |
---|
| 263 | struct element* el; |
---|
| 264 | char name[2*NAME_L]; |
---|
| 265 | char* p; |
---|
| 266 | int i, k, kc; |
---|
| 267 | struct int_array* deco = expr->polish; |
---|
| 268 | for (i = 0; i < deco->curr; i++) /* decoding loop */ |
---|
| 269 | { |
---|
| 270 | if ((k = deco->i[i]) > 4 && (kc = k / 100000000) == 1) |
---|
| 271 | { |
---|
| 272 | k -= 100000000 * kc; strcpy(name, expr_chunks->names[k]); |
---|
| 273 | if ((p = strstr(name, "->")) != NULL) |
---|
| 274 | { |
---|
| 275 | *p = '\0'; |
---|
| 276 | if ((el = find_element(name, element_list)) != NULL) |
---|
| 277 | add_to_el_list(&el, 0, ell, 0); |
---|
| 278 | } |
---|
| 279 | else if ((var = find_variable(name, variable_list)) != NULL) |
---|
| 280 | { |
---|
| 281 | add_to_var_list(var, varl, 2); |
---|
| 282 | if (var->type == 2 && var->expr != NULL) |
---|
| 283 | fill_expr_var_list(ell, var->expr, varl); |
---|
| 284 | } |
---|
| 285 | } |
---|
| 286 | } |
---|
| 287 | } |
---|
| 288 | |
---|
| 289 | double |
---|
| 290 | double_from_expr(char** toks, int s_start, int s_end) |
---|
| 291 | /* returns the value of an expression if valid, else INVALID */ |
---|
| 292 | { |
---|
| 293 | int end, nitem = s_end + 1; |
---|
| 294 | int type = loc_expr(toks, nitem, s_start, &end); |
---|
| 295 | if (type == 1) /* simple number */ |
---|
| 296 | return simple_double(toks, s_start, end); |
---|
| 297 | else if (polish_expr(end + 1 - s_start, &toks[s_start]) == 0) |
---|
| 298 | return polish_value(deco, join( &toks[s_start],end + 1 - s_start) ); |
---|
| 299 | else return INVALID; |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | int |
---|
| 303 | loc_expr(char** items, int nit, int start, int* end) |
---|
| 304 | /* Returns the type and end of an expression, or 0 if illegal */ |
---|
| 305 | { |
---|
| 306 | char c; |
---|
| 307 | int i, e_type = 1, par_level = 0, ltog = -1; |
---|
| 308 | *end = start - 1; |
---|
| 309 | if (nit > start && is_expr_start(*items[start])) |
---|
| 310 | { |
---|
| 311 | c = *items[start]; |
---|
| 312 | for (i = start; i < nit; i++) |
---|
| 313 | { |
---|
| 314 | c = *items[i]; |
---|
| 315 | if (c == '(') {par_level++; e_type = 2;} |
---|
| 316 | else if (c == ')') |
---|
| 317 | { |
---|
| 318 | if (par_level == 0) return 0; |
---|
| 319 | par_level--; ltog = 0; |
---|
| 320 | } |
---|
| 321 | else if (par_level == 0) |
---|
| 322 | { |
---|
| 323 | if (ltog < 0) ltog = is_operator(c) ? 1 : 0; |
---|
| 324 | else if ((ltog == 0 && is_operator(c)) |
---|
| 325 | || (ltog != 0 && is_operand(c))) ltog = 1 - ltog; |
---|
| 326 | else return 0; |
---|
| 327 | } |
---|
| 328 | *end = i; |
---|
| 329 | if ((*end > start && ltog > 0) || (isalpha(c) || c == '_')) e_type = 2; |
---|
| 330 | } |
---|
| 331 | return e_type; |
---|
| 332 | } |
---|
| 333 | else return 0; |
---|
| 334 | } |
---|
| 335 | |
---|
| 336 | int |
---|
| 337 | scan_expr(int c_item, char** item) /* split input */ |
---|
| 338 | |
---|
| 339 | /* scans expressions for parameters, elements, numbers, and functions |
---|
| 340 | |
---|
| 341 | categories: 1: variable, 3: floating constant, 4: operator |
---|
| 342 | operator types: |
---|
| 343 | 1 = +, 2 = -, 3 = *, 4 = /, 5 = ^ (power), 6 = function (from functs) |
---|
| 344 | */ |
---|
| 345 | |
---|
| 346 | { |
---|
| 347 | int i, lp, lx = -1, l_cat = 0, level = 0, pos, f_level[MAX_ITEM]; |
---|
| 348 | char c; |
---|
| 349 | char* bf; |
---|
| 350 | |
---|
| 351 | for (i = 0; i < c_item; i++) /* loop over input items */ |
---|
| 352 | { |
---|
| 353 | c = item[i][0]; /* first character of item i */ |
---|
| 354 | if (c == '(') |
---|
| 355 | { |
---|
| 356 | f_level[level++] = 0; |
---|
| 357 | if (l_cat > 0) |
---|
| 358 | { |
---|
| 359 | if (cat->i[l_cat-1] < 4) return 2; /* error: missing operator */ |
---|
| 360 | if (cat->i[l_cat-1] == 5) /* function */ |
---|
| 361 | { |
---|
| 362 | f_level[level-1] = func->i[--l_cat]; |
---|
| 363 | if (l_cat == func->max) grow_int_array(func); |
---|
| 364 | func->i[l_cat] = 0; |
---|
| 365 | } |
---|
| 366 | } |
---|
| 367 | if (l_cat == cat->max) grow_int_array(cat); |
---|
| 368 | cat->i[l_cat++] = 6; |
---|
| 369 | } |
---|
| 370 | else if (c == ')') |
---|
| 371 | { |
---|
| 372 | if (level == 0) return 1; /* error: too many right brackets */ |
---|
| 373 | if (l_cat == cat->max) grow_int_array(cat); |
---|
| 374 | cat->i[l_cat++] = 7; |
---|
| 375 | level--; |
---|
| 376 | if (f_level[level] != 0) |
---|
| 377 | { |
---|
| 378 | if (l_cat == oper->max) grow_int_array(oper); |
---|
| 379 | if (l_cat == func->max) grow_int_array(func); |
---|
| 380 | if (l_cat == cat->max) grow_int_array(cat); |
---|
| 381 | oper->i[l_cat] = 6; |
---|
| 382 | func->i[l_cat] = f_level[level]; |
---|
| 383 | cat->i[l_cat++] = 4; |
---|
| 384 | } |
---|
| 385 | } |
---|
| 386 | else if (isalpha(c) || c == '_') /* start of variable or function */ |
---|
| 387 | { |
---|
| 388 | lp = 0; |
---|
| 389 | while (strlen(functs[lp])) |
---|
| 390 | { |
---|
| 391 | lx = lp; |
---|
| 392 | if (strcmp(item[i], functs[lp]) == 0) break; |
---|
| 393 | lp++; |
---|
| 394 | } |
---|
| 395 | if (lx == lp) /* function found */ |
---|
| 396 | { |
---|
| 397 | if (l_cat == cat->max) grow_int_array(cat); |
---|
| 398 | if (l_cat == func->max) grow_int_array(func); |
---|
| 399 | cat->i[l_cat] = 5; |
---|
| 400 | func->i[l_cat++] = lp; |
---|
| 401 | if (strcmp("exist", functs[lp]) == 0 /* special function */ |
---|
| 402 | && i+3 < c_item && *item[i+1] == '(' && *item[i+3] == ')') |
---|
| 403 | { |
---|
| 404 | if (find_variable(item[i+2], variable_list) == NULL) |
---|
| 405 | strcpy(item[i+2], "0"); |
---|
| 406 | else strcpy(item[i+2], "1"); |
---|
| 407 | } |
---|
| 408 | } |
---|
| 409 | else |
---|
| 410 | { |
---|
| 411 | if (l_cat == cat->max) grow_int_array(cat); |
---|
| 412 | if (l_cat == d_var->max) grow_int_array(d_var); |
---|
| 413 | cat->i[l_cat] = 1; |
---|
| 414 | if ((pos = name_list_pos(item[i], expr_chunks)) < 0) |
---|
| 415 | { |
---|
| 416 | bf = permbuff(item[i]); |
---|
| 417 | d_var->i[l_cat++] = add_to_name_list(bf, 0, expr_chunks); |
---|
| 418 | } |
---|
| 419 | else d_var->i[l_cat++] = pos; |
---|
| 420 | } |
---|
| 421 | } |
---|
| 422 | else if (isdigit(c) || c == '.') /* number */ |
---|
| 423 | { |
---|
| 424 | if (l_cat == cat->max) grow_int_array(cat); |
---|
| 425 | if (l_cat == cat_doubles->max) grow_double_array(cat_doubles); |
---|
| 426 | cat->i[l_cat] = 3; |
---|
| 427 | cat_doubles->a[l_cat++] = atof(item[i]); |
---|
| 428 | } |
---|
| 429 | else if (is_operator(c)) |
---|
| 430 | { |
---|
| 431 | if (l_cat == cat->max ) grow_int_array(cat); |
---|
| 432 | if (l_cat == oper->max) grow_int_array(oper); |
---|
| 433 | cat->i[l_cat] = 4; |
---|
| 434 | oper->i[l_cat++] = str_pos(op_string, c); |
---|
| 435 | /* oper->i[l_cat++] = (int)strchr(op_string, c) -(int)op_string;*/ |
---|
| 436 | } |
---|
| 437 | else return 2; /* illegal character */ |
---|
| 438 | } |
---|
| 439 | if (level != 0) return 1; /* unclosed parentheses */ |
---|
| 440 | cat->curr = l_cat; |
---|
| 441 | return 0; |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | struct expression* |
---|
| 445 | compound_expr(struct expression* e1, double v1, char* oper, struct expression* e2, double v2) |
---|
| 446 | /* make one out of two expressions, using oper to connect them |
---|
| 447 | hbu 9/2005 moved from madxn.c to makethin.c as only used here |
---|
| 448 | and increased precision sprintf(tmp, "%e" -> sprintf(tmp, "%.14g" */ |
---|
| 449 | { |
---|
| 450 | char** toks = tmp_l_array->p; |
---|
| 451 | struct expression* expr = NULL; |
---|
| 452 | char tmp[30]; |
---|
| 453 | int n; |
---|
| 454 | char lb[] = "(", rb[] = ")"; |
---|
| 455 | if (e1 != NULL || e2 != NULL) |
---|
| 456 | { |
---|
| 457 | if (e1 != NULL) |
---|
| 458 | { |
---|
| 459 | if (e2 != NULL) |
---|
| 460 | { |
---|
| 461 | toks[0] = lb; toks[1] = e1->string; toks[2] = rb; |
---|
| 462 | toks[3] = oper; |
---|
| 463 | toks[4] = lb; toks[5] = e2->string; toks[6] = rb; |
---|
| 464 | } |
---|
| 465 | else |
---|
| 466 | { |
---|
| 467 | sprintf(tmp, "%.14g", v2); /* hbu */ |
---|
| 468 | toks[0] = lb; toks[1] = e1->string; toks[2] = rb; |
---|
| 469 | toks[3] = oper; |
---|
| 470 | toks[4] = lb; toks[5] = tmp; toks[6] = rb; |
---|
| 471 | } |
---|
| 472 | } |
---|
| 473 | else |
---|
| 474 | { |
---|
| 475 | sprintf(tmp, "%.14g", v1); /* hbu */ |
---|
| 476 | toks[0] = lb; toks[1] = tmp; toks[2] = rb; |
---|
| 477 | toks[3] = oper; |
---|
| 478 | toks[4] = lb; toks[5] = e2->string; toks[6] = rb; |
---|
| 479 | } |
---|
| 480 | join(toks, 7); |
---|
| 481 | pre_split(c_join->c, l_wrk, 0); |
---|
| 482 | n = mysplit(l_wrk->c, tmp_l_array); |
---|
| 483 | expr = make_expression(n, toks); |
---|
| 484 | } |
---|
| 485 | return expr; |
---|
| 486 | } |
---|
| 487 | |
---|
| 488 | /* scale an expression by a number - or leave it NULL */ |
---|
| 489 | struct expression* |
---|
| 490 | scale_expr(struct expression* expr,double scale) |
---|
| 491 | { |
---|
| 492 | if (expr) return compound_expr(expr,0,"*",NULL,scale); |
---|
| 493 | return NULL; |
---|
| 494 | } |
---|
| 495 | |
---|