1 | #include "madx.h" |
---|
2 | |
---|
3 | static double |
---|
4 | act_value(int pos, struct name_list* chunks) |
---|
5 | /* returns the actual value of a variable, element, or command parameter */ |
---|
6 | { |
---|
7 | char* name = chunks->names[pos]; |
---|
8 | char comm[NAME_L]; |
---|
9 | char par[NAME_L]; |
---|
10 | char *p, *n = name, *q = comm; |
---|
11 | double val = zero; |
---|
12 | struct element* el; |
---|
13 | struct command* cmd = NULL; |
---|
14 | if ((p = strstr(name, "->")) == NULL) /* variable */ |
---|
15 | { |
---|
16 | if ((current_variable = find_variable(name, variable_list)) == NULL) |
---|
17 | { |
---|
18 | if (get_option("verify")) |
---|
19 | warning("undefined variable set to zero:", name); |
---|
20 | current_variable = new_variable(name, zero, 1, 1, NULL, NULL); |
---|
21 | val = zero; |
---|
22 | add_to_var_list(current_variable, variable_list, 0); |
---|
23 | } |
---|
24 | else val = variable_value(current_variable); |
---|
25 | } |
---|
26 | else /* element or command parameter */ |
---|
27 | { |
---|
28 | while (n < p) *(q++) = *(n++); |
---|
29 | *q = '\0'; |
---|
30 | q = par; n++; n++; |
---|
31 | while (*n != '\0') *(q++) = *(n++); |
---|
32 | *q = '\0'; |
---|
33 | if (strncmp(comm, "beam", 4) == 0) |
---|
34 | { |
---|
35 | cmd = current_beam = find_command("default_beam", beam_list); |
---|
36 | if ((p = strchr(comm, '%')) != NULL) |
---|
37 | { |
---|
38 | if ((current_beam = find_command(++p, beam_list)) == NULL) |
---|
39 | current_beam = cmd; |
---|
40 | } |
---|
41 | val = command_par_value(par, current_beam); |
---|
42 | } |
---|
43 | else if ((el = find_element(comm, element_list)) != NULL) |
---|
44 | val = el_par_value(par, el); |
---|
45 | else if ((cmd = find_command(comm, stored_commands)) != NULL) |
---|
46 | val = command_par_value(par, cmd); |
---|
47 | else if ((cmd = find_command(comm, beta0_list)) != NULL) |
---|
48 | val = command_par_value(par, cmd); |
---|
49 | else if ((cmd = find_command(comm, defined_commands)) != NULL) |
---|
50 | val = command_par_value(par, cmd); |
---|
51 | } |
---|
52 | return val; |
---|
53 | } |
---|
54 | |
---|
55 | static int |
---|
56 | simple_logic_expr(int nit, char* toks[]) |
---|
57 | /* evaluates a logical expression of type expr1 op expr2 |
---|
58 | where op is one of ==, <>, <, >, <=, >= |
---|
59 | returns -1 if invalid |
---|
60 | 0 if false |
---|
61 | 1 if true */ |
---|
62 | { |
---|
63 | int i, t1, t2, l1_start, l1_end, l2_start, l2_end, |
---|
64 | logex = -1, brack = 0; |
---|
65 | double val1, val2; |
---|
66 | char c; |
---|
67 | |
---|
68 | for (i = 0; i < nit; i++) |
---|
69 | { |
---|
70 | c = *toks[i]; |
---|
71 | switch (c) |
---|
72 | { |
---|
73 | case '(': |
---|
74 | brack++; |
---|
75 | break; |
---|
76 | case ')': |
---|
77 | brack--; |
---|
78 | break; |
---|
79 | case '<': |
---|
80 | case '>': |
---|
81 | case '=': |
---|
82 | if (brack == 0) goto found; |
---|
83 | } |
---|
84 | } |
---|
85 | return -1; |
---|
86 | found: |
---|
87 | l1_start = 0; |
---|
88 | l2_start = (*toks[i+1] == '=' || *toks[i+1] == '>') ? i + 2 : i + 1; |
---|
89 | if ((t1 = loc_expr(toks, i, l1_start, &l1_end)) == 0) return -1; |
---|
90 | if (t1 == 2) |
---|
91 | { |
---|
92 | if (polish_expr(l1_end + 1 - l1_start, &toks[l1_start]) == 0) |
---|
93 | val1 = polish_value(deco, join(&toks[l1_start], l1_end + 1 - l1_start)); |
---|
94 | else return -1; |
---|
95 | } |
---|
96 | else val1 = simple_double(toks, l1_start, l1_end); |
---|
97 | if ((t2 = loc_expr(toks, nit, l2_start, &l2_end)) == 0) return -1; |
---|
98 | if (t2 == 2) |
---|
99 | { |
---|
100 | if (polish_expr(l2_end + 1 - l2_start, &toks[l2_start]) == 0) |
---|
101 | val2 = polish_value(deco, join(&toks[l2_start], l2_end + 1 - l2_start)); |
---|
102 | else return -1; |
---|
103 | } |
---|
104 | else val2 = simple_double(toks, l2_start, l2_end); |
---|
105 | if (c == '<') |
---|
106 | { |
---|
107 | if (*toks[i+1] == '=') logex = val1 <= val2 ? 1 : 0; |
---|
108 | else if(*toks[i+1] == '>') logex = val1 != val2 ? 1 : 0; |
---|
109 | else logex = val1 < val2 ? 1 : 0; |
---|
110 | } |
---|
111 | else if (c == '>') |
---|
112 | { |
---|
113 | if (*toks[i+1] == '=') logex = val1 >= val2 ? 1 : 0; |
---|
114 | else logex = val1 > val2 ? 1 : 0; |
---|
115 | } |
---|
116 | else if (c == '=' && *toks[i+1] == '=') logex = val1 == val2 ? 1 : 0; |
---|
117 | return logex; |
---|
118 | } |
---|
119 | |
---|
120 | static int |
---|
121 | logic_expr(int nit, char* toks[]) |
---|
122 | { |
---|
123 | /* evaluates composite logical expression of type simple1 op simple2, |
---|
124 | where simple1 and simple2 are simple logical expressions, and |
---|
125 | op is either || or &&; |
---|
126 | returns -1 for invalid |
---|
127 | 0 for false |
---|
128 | 1 for true */ |
---|
129 | int i = 0, k; |
---|
130 | char c = ' '; |
---|
131 | |
---|
132 | for (i = 0; i < nit; i++) |
---|
133 | { |
---|
134 | if (*toks[i] == '|' || *toks[i] == '&') |
---|
135 | { |
---|
136 | c = *toks[i]; break; |
---|
137 | } |
---|
138 | } |
---|
139 | if (i == nit) return simple_logic_expr(nit, toks); |
---|
140 | if (++i == nit || *toks[i] != c) return -1; |
---|
141 | k = simple_logic_expr(i-1, toks); |
---|
142 | if (c == '|') |
---|
143 | { |
---|
144 | if (k != 0) return 1; |
---|
145 | else if (++i == nit) return -1; |
---|
146 | else return simple_logic_expr(nit-i, &toks[i]); |
---|
147 | } |
---|
148 | else |
---|
149 | { |
---|
150 | if (k == 0) return 0; |
---|
151 | else if (++i == nit) return -1; |
---|
152 | else return simple_logic_expr(nit-i, &toks[i]); |
---|
153 | } |
---|
154 | } |
---|
155 | |
---|
156 | // public interface |
---|
157 | |
---|
158 | void |
---|
159 | deco_init(void) |
---|
160 | /* initializes Polish decoding */ |
---|
161 | { |
---|
162 | expr_chunks = new_name_list("expr_chunks", 2000); |
---|
163 | cat = new_int_array(MAX_ITEM); |
---|
164 | deco = new_int_array(MAX_ITEM); |
---|
165 | d_var = new_int_array(MAX_ITEM); |
---|
166 | oper = new_int_array(MAX_ITEM); |
---|
167 | func = new_int_array(MAX_ITEM); |
---|
168 | cat_doubles = new_double_array(MAX_ITEM); |
---|
169 | doubles = new_double_array(MAX_D_ITEM); |
---|
170 | twiss_deltas = new_double_array(MAX_ITEM); |
---|
171 | } |
---|
172 | |
---|
173 | int |
---|
174 | act_special(int type, char* statement) |
---|
175 | /* acts on special commands (IF{..} etc.) */ |
---|
176 | { |
---|
177 | struct char_array* loc_buff = NULL; |
---|
178 | struct char_array* loc_w = NULL; |
---|
179 | int cnt_1, start_2, rs, re, level = pro->curr, ls = strlen(statement); |
---|
180 | int ret_val = 0; |
---|
181 | struct char_p_array* logic; |
---|
182 | int logex = 0; |
---|
183 | char *cp = statement; |
---|
184 | if (ls < IN_BUFF_SIZE) ls = IN_BUFF_SIZE; |
---|
185 | if (level == pro->max) grow_in_buff_list(pro); |
---|
186 | if (pro->buffers[level] == NULL) |
---|
187 | pro->buffers[level] = new_in_buffer(ls); |
---|
188 | else |
---|
189 | { |
---|
190 | while(pro->buffers[level]->c_a->max < ls) |
---|
191 | grow_char_array(pro->buffers[level]->c_a); |
---|
192 | } |
---|
193 | if (type == 5) /* macro */ return make_macro(statement); |
---|
194 | else if (type == 6) /* line */ return make_line(statement); |
---|
195 | logic = new_char_p_array(1000); |
---|
196 | loc_buff = new_char_array(ls); |
---|
197 | loc_w = new_char_array(ls); |
---|
198 | get_bracket_range(statement, '{', '}', &rs, &re); |
---|
199 | if (re < 0) fatal_error("missing '{' or '}' in statement:",statement); |
---|
200 | cnt_1 = rs; start_2 = rs + 1; |
---|
201 | mystrcpy(loc_buff, statement); loc_buff->c[re] = '\0'; |
---|
202 | while(aux_buff->max < cnt_1) grow_char_array(aux_buff); |
---|
203 | strncpy(aux_buff->c, statement, cnt_1); aux_buff->c[cnt_1] = '\0'; |
---|
204 | switch (type) |
---|
205 | { |
---|
206 | case 1: /* if */ |
---|
207 | pro->buffers[level]->flag = 0; |
---|
208 | case 3: /* else if */ |
---|
209 | if (pro->buffers[level]->flag < 0) |
---|
210 | { |
---|
211 | ret_val = -1; |
---|
212 | break; |
---|
213 | } |
---|
214 | if (pro->buffers[level]->flag == 0) |
---|
215 | { |
---|
216 | pre_split(aux_buff->c, loc_w, 0); |
---|
217 | mysplit(loc_w->c, tmp_l_array); |
---|
218 | get_bracket_t_range(tmp_l_array->p, '(', ')', 0, tmp_l_array->curr, |
---|
219 | &rs, &re); |
---|
220 | rs++; |
---|
221 | if ((logex = logic_expr(re-rs, &tmp_l_array->p[rs])) > 0) |
---|
222 | { |
---|
223 | pro->buffers[level]->flag = 1; |
---|
224 | pro->curr++; |
---|
225 | /* now loop over statements inside {...} */ |
---|
226 | pro_input(&loc_buff->c[start_2]); |
---|
227 | pro->curr--; |
---|
228 | } |
---|
229 | else if (logex < 0) warning("illegal if construct set false:", cp); |
---|
230 | } |
---|
231 | break; |
---|
232 | case 2: /* else */ |
---|
233 | if (pro->buffers[level]->flag < 0) |
---|
234 | { |
---|
235 | ret_val = -1; |
---|
236 | break; |
---|
237 | } |
---|
238 | if (pro->buffers[level]->flag == 0) |
---|
239 | { |
---|
240 | pro->curr++; |
---|
241 | /* now loop over statements inside {...} */ |
---|
242 | pro_input(&loc_buff->c[start_2]); |
---|
243 | pro->curr--; |
---|
244 | pro->buffers[level]->flag = -1; |
---|
245 | } |
---|
246 | break; |
---|
247 | case 4: /* while */ |
---|
248 | pre_split(aux_buff->c, loc_w, 0); |
---|
249 | mysplit(loc_w->c, logic); |
---|
250 | get_bracket_t_range(logic->p, '(', ')', 0, logic->curr, |
---|
251 | &rs, &re); |
---|
252 | pro->curr++; rs++; |
---|
253 | while ((logex = logic_expr(re-rs, &logic->p[rs])) > 0) |
---|
254 | { |
---|
255 | /* now loop over statements inside {...} */ |
---|
256 | pro_input(&loc_buff->c[start_2]); |
---|
257 | } |
---|
258 | pro->curr--; |
---|
259 | break; |
---|
260 | default: |
---|
261 | ret_val = -1; |
---|
262 | } |
---|
263 | if (loc_buff != NULL) delete_char_array(loc_buff); |
---|
264 | if (loc_w != NULL) delete_char_array(loc_w); |
---|
265 | delete_char_p_array(logic, 0); |
---|
266 | return ret_val; |
---|
267 | } |
---|
268 | |
---|
269 | void |
---|
270 | pro_input(char* statement) |
---|
271 | /* processes one special (IF() etc.), or one normal statement after input */ |
---|
272 | { |
---|
273 | int type, code, nnb, ktmp; |
---|
274 | char* sem; |
---|
275 | int rs, re, start = 0, l = strlen(statement); |
---|
276 | |
---|
277 | clearerrorflag(); /*reset global error flag */ |
---|
278 | |
---|
279 | while (start < l) |
---|
280 | { |
---|
281 | if ((type = in_spec_list(&statement[start]))) |
---|
282 | { |
---|
283 | if (type == 6) |
---|
284 | { |
---|
285 | get_bracket_range(&statement[start], '(', ')', &rs, &re); |
---|
286 | ktmp = re+1; |
---|
287 | if (re > rs && strchr(&statement[ktmp], ':')) /* formal arg.s */ |
---|
288 | { |
---|
289 | get_bracket_range(&statement[ktmp], '(', ')', &rs, &re); |
---|
290 | rs += ktmp; re += ktmp; |
---|
291 | } |
---|
292 | } |
---|
293 | else get_bracket_range(&statement[start], '{', '}', &rs, &re); |
---|
294 | if (re > rs) |
---|
295 | { |
---|
296 | re += start + 1; |
---|
297 | if (re < l && next_non_blank(&statement[re]) == ';') |
---|
298 | re += next_non_blank_pos(&statement[re]) + 1; |
---|
299 | } |
---|
300 | if((code = act_special(type, &statement[start])) < 0) |
---|
301 | { |
---|
302 | if (get_option("warn")) |
---|
303 | { |
---|
304 | switch (code) |
---|
305 | { |
---|
306 | case -1: |
---|
307 | warning("statement illegal in this context,", "skipped"); |
---|
308 | break; |
---|
309 | case -2: |
---|
310 | warning("statement label is protected keyword,", "skipped"); |
---|
311 | case -3: |
---|
312 | warning("statement not recognised:", statement); |
---|
313 | break; |
---|
314 | default: |
---|
315 | fatal_error("illegal return code","from act_special"); |
---|
316 | } |
---|
317 | } |
---|
318 | } |
---|
319 | if (re > rs && re < l) |
---|
320 | { |
---|
321 | if (next_non_blank_pos(&statement[re]) < 0) start = l; |
---|
322 | else start = re; |
---|
323 | } |
---|
324 | else start = l; |
---|
325 | } |
---|
326 | else |
---|
327 | { |
---|
328 | if ((sem = mystrchr(&statement[start], ';')) == NULL) return; |
---|
329 | if (sem > &statement[start]) /* skip empty ';' */ |
---|
330 | { |
---|
331 | *sem = '\0'; |
---|
332 | this_cmd = new_in_cmd(400); |
---|
333 | pre_split(&statement[start], work, 1); |
---|
334 | check_table(work->c); check_tabstring(work->c); |
---|
335 | this_cmd->tok_list->curr = mysplit(work->c, this_cmd->tok_list); |
---|
336 | if ((type = decode_command()) < 0) /* error */ |
---|
337 | { |
---|
338 | if (get_option("warn")) |
---|
339 | { |
---|
340 | switch (type) |
---|
341 | { |
---|
342 | case -1: |
---|
343 | warning("statement illegal in this context,", "skipped"); |
---|
344 | break; |
---|
345 | case -2: |
---|
346 | warning("statement label is protected keyword,","skipped"); |
---|
347 | case -3: |
---|
348 | warning("statement not recognised:", work->c); |
---|
349 | break; |
---|
350 | default: |
---|
351 | fatal_error("illegal return code","from decode_command"); |
---|
352 | } |
---|
353 | } |
---|
354 | } |
---|
355 | else process(); |
---|
356 | if (stop_flag) return; |
---|
357 | *sem = ';'; |
---|
358 | } |
---|
359 | sem++; |
---|
360 | start = sem - statement; |
---|
361 | if (start < l) |
---|
362 | { |
---|
363 | if ((nnb = next_non_blank_pos(sem)) < 0) start = l; |
---|
364 | else start += nnb; |
---|
365 | } |
---|
366 | } |
---|
367 | } |
---|
368 | } |
---|
369 | |
---|
370 | void |
---|
371 | process(void) /* steering routine: processes one command */ |
---|
372 | { |
---|
373 | int pos; |
---|
374 | char* name; |
---|
375 | struct element* el; |
---|
376 | if (this_cmd != NULL) |
---|
377 | { |
---|
378 | |
---|
379 | switch (this_cmd->type) |
---|
380 | { |
---|
381 | case 0: /* executable commands */ |
---|
382 | exec_command(); |
---|
383 | if (stop_flag) |
---|
384 | { |
---|
385 | if (this_cmd) |
---|
386 | { |
---|
387 | if (this_cmd->clone != NULL) |
---|
388 | this_cmd->clone = delete_command(this_cmd->clone); |
---|
389 | this_cmd = delete_in_cmd(this_cmd); |
---|
390 | } |
---|
391 | return; |
---|
392 | } |
---|
393 | break; |
---|
394 | case 1: /* element definition */ |
---|
395 | enter_element(this_cmd); |
---|
396 | buffer_in_cmd(this_cmd); |
---|
397 | break; |
---|
398 | case 2: /* variable definition */ |
---|
399 | enter_variable(this_cmd); |
---|
400 | break; |
---|
401 | case 3: /* sequence start or end */ |
---|
402 | enter_sequence(this_cmd); |
---|
403 | break; |
---|
404 | case 4: |
---|
405 | name = this_cmd->tok_list->p[0]; |
---|
406 | if (sequ_is_on) |
---|
407 | /* element or sequence reference in sequence */ |
---|
408 | { |
---|
409 | if ((pos = name_list_pos(name, sequences->list)) < 0) |
---|
410 | enter_element(this_cmd); |
---|
411 | else |
---|
412 | { |
---|
413 | this_cmd->cmd_def = find_command("sequence", defined_commands); |
---|
414 | this_cmd->clone = clone_command(this_cmd->cmd_def); |
---|
415 | strcpy(this_cmd->clone->name, name); |
---|
416 | scan_in_cmd(this_cmd); |
---|
417 | enter_sequ_reference(this_cmd, sequences->sequs[pos]); |
---|
418 | } |
---|
419 | } |
---|
420 | else |
---|
421 | /* element parameter definition */ |
---|
422 | { |
---|
423 | if ((el = find_element(name, element_list)) == NULL) |
---|
424 | warning("skipped, command or element unknown:", name); |
---|
425 | else |
---|
426 | { |
---|
427 | this_cmd->cmd_def = el->def; |
---|
428 | this_cmd->clone = clone_command(this_cmd->cmd_def); |
---|
429 | strcpy(this_cmd->clone->name, name); |
---|
430 | scan_in_cmd(this_cmd); |
---|
431 | update_element(el, this_cmd->clone); |
---|
432 | } |
---|
433 | } |
---|
434 | break; |
---|
435 | default: |
---|
436 | warning("unknown command type:", |
---|
437 | join_b(this_cmd->tok_list->p, this_cmd->tok_list->curr)); |
---|
438 | } |
---|
439 | if (this_cmd != NULL && (this_cmd->type == 0 || this_cmd->type == 2)) |
---|
440 | { |
---|
441 | if (this_cmd->clone != NULL) |
---|
442 | { |
---|
443 | if (this_cmd->clone_flag == 0) |
---|
444 | this_cmd->clone = delete_command(this_cmd->clone); |
---|
445 | else add_to_command_list(this_cmd->clone->name, |
---|
446 | this_cmd->clone, stored_commands, 0); |
---|
447 | } |
---|
448 | if (this_cmd->label != NULL) buffer_in_cmd(this_cmd); |
---|
449 | else this_cmd = delete_in_cmd(this_cmd); |
---|
450 | } |
---|
451 | } |
---|
452 | } |
---|
453 | |
---|
454 | int |
---|
455 | polish_expr(int c_item, char** item) /* split input */ |
---|
456 | /* deco output array containing: |
---|
457 | expression in Polish notation of length deco->curr, |
---|
458 | coded as 0-, 1+, 2*, 3/, 4^ (power), |
---|
459 | 6 evaluate function |
---|
460 | 100000000 + n = variable n (refers to vars), |
---|
461 | 200000000 + n = function n (refers to functs), |
---|
462 | 400000000 + n = real n (refers to doubles) |
---|
463 | -- Example: suppose a, b are variables 0 and 4, exp is function 3: |
---|
464 | then 3 * a * q[l] * q[k1] / exp((b - 1.57)^2) + 1.57 |
---|
465 | would result in |
---|
466 | 400000000 100000000 2 100000001 2 100000002 2 |
---|
467 | 100000003 400000001 0 400000002 3 200000003 3 400000001 1 |
---|
468 | where 3 = real 0, 1.57 = real 1, 2 = real 2 |
---|
469 | a = vars 0, q[l] vars 1, q[k1] vars 2, exp functs 3 |
---|
470 | */ |
---|
471 | { |
---|
472 | int i, j, error, op, id, stack = 0, l_deco, l_double; |
---|
473 | int up[100][3] = {{-1, -1, -1}}; |
---|
474 | |
---|
475 | l_deco = deco->curr = 0; |
---|
476 | l_double = doubles->curr; |
---|
477 | error = scan_expr(c_item, item); |
---|
478 | if (error) return error; |
---|
479 | for (i = 0; i < cat->curr; i++) |
---|
480 | { |
---|
481 | |
---|
482 | /* categories: 1: variable, 3: floating constant, 4: operator |
---|
483 | 6: left par., 7: right par. */ |
---|
484 | switch (cat->i[i]) |
---|
485 | { |
---|
486 | case 1: /* variable */ |
---|
487 | if (l_deco == deco->max) grow_int_array(deco); |
---|
488 | deco->i[l_deco++] = 100000000 + d_var->i[i]; |
---|
489 | break; |
---|
490 | case 3: /* constant */ |
---|
491 | if (l_deco == deco->max) grow_int_array(deco); |
---|
492 | if (l_double == doubles->max) grow_double_array(doubles); |
---|
493 | doubles->a[l_double] = cat_doubles->a[i]; |
---|
494 | deco->i[l_deco++] = 400000000 + l_double++; |
---|
495 | doubles->curr = l_double; |
---|
496 | break; |
---|
497 | case 4: |
---|
498 | if ((op = oper->i[i]) < 5) /* operator */ |
---|
499 | { |
---|
500 | id = op / 2; |
---|
501 | for (j = 2; j >= id; j--) |
---|
502 | { |
---|
503 | if (up[stack][j] > -1) |
---|
504 | { |
---|
505 | if (l_deco == deco->max) grow_int_array(deco); |
---|
506 | deco->i[l_deco++] = up[stack][j]; |
---|
507 | up[stack][j] = -1; |
---|
508 | } |
---|
509 | } |
---|
510 | up[stack][id] = op; |
---|
511 | } |
---|
512 | else |
---|
513 | { |
---|
514 | if (l_deco == deco->max) grow_int_array(deco); |
---|
515 | deco->i[l_deco++] = 200000000 + func->i[i]; /* function */ |
---|
516 | } |
---|
517 | break; |
---|
518 | case 6: /* '(' */ |
---|
519 | stack++; |
---|
520 | for (j = 0; j < 3; j++) up[stack][j] = -1; |
---|
521 | break; |
---|
522 | case 7: /* ')' */ |
---|
523 | for (j = 2; j >= 0; j--) |
---|
524 | { |
---|
525 | if (up[stack][j] > -1) |
---|
526 | { |
---|
527 | if (l_deco == deco->max) grow_int_array(deco); |
---|
528 | deco->i[l_deco++] = up[stack][j]; |
---|
529 | } |
---|
530 | } |
---|
531 | stack--; |
---|
532 | break; |
---|
533 | default: |
---|
534 | return 9; |
---|
535 | } /* end switch */ |
---|
536 | } /* end loop over categories */ |
---|
537 | for (j = 2; j >= 0; j--) /* clear stack */ |
---|
538 | { |
---|
539 | if (up[stack][j] > -1) |
---|
540 | { |
---|
541 | if (l_deco == deco->max) grow_int_array(deco); |
---|
542 | deco->i[l_deco++] = up[stack][j]; |
---|
543 | } |
---|
544 | } |
---|
545 | deco->curr = l_deco; |
---|
546 | return 0; |
---|
547 | } |
---|
548 | |
---|
549 | double |
---|
550 | polish_value(struct int_array* deco, char* expr_string) |
---|
551 | /* coded input (see below) */ |
---|
552 | /* description see polish_expression */ |
---|
553 | { |
---|
554 | int i, k, kc, c_stack = -1; |
---|
555 | double stack[MAX_ITEM]; |
---|
556 | char tmp[20]; |
---|
557 | |
---|
558 | if (++polish_cnt > MAX_LOOP) |
---|
559 | fatal_error("circular call in expression", expr_string); |
---|
560 | stack[0] = 0; |
---|
561 | for (i = 0; i < deco->curr; i++) /* decoding loop */ |
---|
562 | { |
---|
563 | k = deco->i[i]; |
---|
564 | if ( k < 5) /* operator */ |
---|
565 | { |
---|
566 | if (c_stack < 0) |
---|
567 | { |
---|
568 | fatal_error("stack underflow in expression:", expr_string); |
---|
569 | } |
---|
570 | else if (c_stack == 0) |
---|
571 | { |
---|
572 | stack[1] = stack[0]; stack[0] = 0; |
---|
573 | } |
---|
574 | else c_stack--; |
---|
575 | |
---|
576 | |
---|
577 | switch(k) |
---|
578 | { |
---|
579 | case 0: |
---|
580 | stack[c_stack] -= stack[c_stack+1]; |
---|
581 | break; |
---|
582 | case 1: |
---|
583 | stack[c_stack] += stack[c_stack+1]; |
---|
584 | break; |
---|
585 | case 2: |
---|
586 | stack[c_stack] *= stack[c_stack+1]; |
---|
587 | break; |
---|
588 | case 3: |
---|
589 | if (stack[c_stack+1] == 0.0) |
---|
590 | { |
---|
591 | warning("division by zero, result set to zero, expr:", expr_string); |
---|
592 | stack[c_stack] = 0.0; |
---|
593 | break; |
---|
594 | } |
---|
595 | stack[c_stack] /= stack[c_stack+1]; |
---|
596 | break; |
---|
597 | case 4: |
---|
598 | stack[c_stack] = pow(stack[c_stack],stack[c_stack+1]); |
---|
599 | break; |
---|
600 | default: |
---|
601 | fatal_error("illegal operator, Polish, expr.:", expr_string); |
---|
602 | } |
---|
603 | } |
---|
604 | else |
---|
605 | { |
---|
606 | kc = k / 100000000; k -= 100000000 * kc; |
---|
607 | switch(kc) |
---|
608 | { |
---|
609 | case 1: /* variable */ |
---|
610 | stack[++c_stack] = act_value(k, expr_chunks); |
---|
611 | break; |
---|
612 | case 4: /* real constant */ |
---|
613 | stack[++c_stack] = doubles->a[k]; |
---|
614 | break; |
---|
615 | case 2: /* function */ |
---|
616 | switch(k-1) /* the offset is due to dummyfunction */ |
---|
617 | { |
---|
618 | case 0: |
---|
619 | stack[c_stack] = fabs(stack[c_stack]); |
---|
620 | break; |
---|
621 | case 1: |
---|
622 | stack[c_stack] = sqrt(stack[c_stack]); |
---|
623 | break; |
---|
624 | case 2: |
---|
625 | stack[c_stack] = exp(stack[c_stack]); |
---|
626 | break; |
---|
627 | case 3: |
---|
628 | stack[c_stack] = log(stack[c_stack]); |
---|
629 | break; |
---|
630 | case 4: |
---|
631 | stack[c_stack] = log10(stack[c_stack]); |
---|
632 | break; |
---|
633 | case 5: |
---|
634 | stack[c_stack] = sin(stack[c_stack]); |
---|
635 | break; |
---|
636 | case 6: |
---|
637 | stack[c_stack] = cos(stack[c_stack]); |
---|
638 | break; |
---|
639 | case 7: |
---|
640 | stack[c_stack] = tan(stack[c_stack]); |
---|
641 | break; |
---|
642 | case 8: |
---|
643 | stack[c_stack] = asin(stack[c_stack]); |
---|
644 | break; |
---|
645 | case 9: |
---|
646 | stack[c_stack] = acos(stack[c_stack]); |
---|
647 | break; |
---|
648 | case 10: |
---|
649 | stack[c_stack] = atan(stack[c_stack]); |
---|
650 | break; |
---|
651 | case 11: |
---|
652 | stack[c_stack] = sinh(stack[c_stack]); |
---|
653 | break; |
---|
654 | case 12: |
---|
655 | stack[c_stack] = cosh(stack[c_stack]); |
---|
656 | break; |
---|
657 | case 13: |
---|
658 | stack[c_stack] = tanh(stack[c_stack]); |
---|
659 | break; |
---|
660 | case 14: |
---|
661 | stack[c_stack] = frndm(); |
---|
662 | break; |
---|
663 | case 15: |
---|
664 | stack[c_stack] = grndm(); |
---|
665 | break; |
---|
666 | case 16: |
---|
667 | stack[c_stack] = tgrndm(stack[c_stack]); |
---|
668 | break; |
---|
669 | case 17: |
---|
670 | stack[c_stack] = table_value(); |
---|
671 | break; |
---|
672 | case 18: /* function "exist" */ |
---|
673 | continue; /* value in stack not changed */ |
---|
674 | break; |
---|
675 | case 19: |
---|
676 | stack[c_stack] = floor(stack[c_stack]); |
---|
677 | break; |
---|
678 | case 20: |
---|
679 | stack[c_stack] = ceil(stack[c_stack]); |
---|
680 | break; |
---|
681 | case 21: |
---|
682 | stack[c_stack] = rint(stack[c_stack]); |
---|
683 | break; |
---|
684 | case 22: { |
---|
685 | double int_part; |
---|
686 | stack[c_stack] = modf(stack[c_stack], &int_part); |
---|
687 | } break; |
---|
688 | default: |
---|
689 | fatal_error("polish_value: illegal function in expr:", |
---|
690 | expr_string); |
---|
691 | } |
---|
692 | break; |
---|
693 | default: |
---|
694 | /* if you get here, then most likely someone has created |
---|
695 | more than 100000000 double precision numbers */ |
---|
696 | sprintf(tmp, "%d", k-1); |
---|
697 | fatal_error("illegal type in Polish decoding: ", tmp); |
---|
698 | exit(1); |
---|
699 | } |
---|
700 | } |
---|
701 | } /* end of decoding loop */ |
---|
702 | polish_cnt--; |
---|
703 | return stack[0]; |
---|
704 | } |
---|
705 | |
---|
706 | void |
---|
707 | print_value(struct in_cmd* cmd) |
---|
708 | { |
---|
709 | char** toks = &cmd->tok_list->p[cmd->decl_start]; |
---|
710 | int n = cmd->tok_list->curr - cmd->decl_start; |
---|
711 | int j, s_start = 0, end, nitem; // , type // not used |
---|
712 | while (s_start < n) |
---|
713 | { |
---|
714 | for (j = s_start; j < n; j++) if (*toks[j] == ',') break; |
---|
715 | if (loc_expr(toks, j, s_start, &end) > 0) // type = // not used |
---|
716 | { |
---|
717 | nitem = end + 1 - s_start; |
---|
718 | if (polish_expr(nitem, &toks[s_start]) == 0) |
---|
719 | fprintf(prt_file, v_format("%s = %F ;\n"), |
---|
720 | spec_join(&toks[s_start], nitem), |
---|
721 | polish_value(deco, join(&toks[s_start], nitem))); |
---|
722 | else |
---|
723 | { |
---|
724 | warning("invalid expression:", spec_join(&toks[s_start], nitem)); |
---|
725 | return; |
---|
726 | } |
---|
727 | s_start = end+1; |
---|
728 | if (s_start < n-1 && *toks[s_start] == ',') s_start++; |
---|
729 | } |
---|
730 | else |
---|
731 | { |
---|
732 | warning("invalid expression:", spec_join(&toks[s_start], n)); |
---|
733 | return; |
---|
734 | } |
---|
735 | } |
---|
736 | } |
---|
737 | |
---|