generic makefile
[calc.git] / parser.c
CommitLineData
f2927108 1#include <math.h>
87621fe1 2#include <stdio.h>
bc97a989 3#include <stdlib.h>
b9c1c40d 4#include <string.h>
bc97a989 5
a24bd519 6#include "alloc.h"
c91672f9 7#include "argument.h"
bc97a989 8#include "debug.h"
a24bd519
LM
9#include "element.h"
10#include "format.h"
11#include "program.h"
12#include "stack.h"
13#include "storage.h"
bc97a989
LM
14
15#include "parser.h"
16
33376ef0
LM
17/* external definition */
18
19extern void history ();
20
5075f6ea
LM
21/* global variables */
22
23double answer = 0;
24
807bdeba
LM
25double anglefactor = 1;
26
bc97a989
LM
27/* compare codes */
28
29int codecmp (char *ref, char *str)
30{
31 int sig;
32
33 while (*ref != '\0') {
0b9cc9b0
LM
34 if (*ref == '\t') {
35 sig = (*str == '.') ? -1 : ((*str >= '0') && (*str <= '9'));
36 } else {
37 sig = *str - *ref;
38 }
bc97a989
LM
39 if (sig != 0) {
40 return (sig > 0) ? 1 : -1;
41 }
0b9cc9b0
LM
42 str++;
43 ref++;
bc97a989
LM
44 }
45
46 return 0;
47}
48
d2ff8478
LM
49/* subparser function */
50
51element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, int prio)
52{
53 element_t *new = newelement (func, nbops, prio);
d2ff8478
LM
54 new->ops[0] = *proot;
55 new->ops[1] = parser (*pstr, pstr, new->prio);
686c4bc2 56 if ((new->ops[1] == NULL) || ((new->ops[1] != ERROR_OP) && (new->ops[1]->prio == 9))) {
67b13e3d
LM
57 delelement (new->ops[1]);
58 new->ops[1] = ERROR_OP;
59 }
d2ff8478 60 if (new->ops[1] == ERROR_OP) {
031d7bba
LM
61 delelement (new);
62 *proot = NULL;
d2ff8478
LM
63 return ERROR_OP;
64 }
3b4b0bbe 65 *proot = newelement (Val, 1, 5);
d2ff8478
LM
66 (*proot)->ops[0] = new;
67
68 return *proot;
69}
70
bc97a989
LM
71/* parser function */
72
ef37d966 73element_t *parser (char *str, char **next, int prio)
0b489a77 74{
bc97a989 75 element_t *root = NULL;
779282bb 76 char *string = str;
bc97a989 77
04d68907 78 VERBOSE (DEBUG, fprintf (stdout, "Starting parsing\n"));
49223129 79
bc97a989
LM
80 /* main loop */
81 while (*str != '\0') {
82 int found = 0;
83 element_t *new = NULL;
04d68907 84 VERBOSE (INFO, fprintf (stdout, "Processing: %s\n", str));
bc97a989 85
2d0cd54c
LM
86 /* end without printing */
87
88 if (*str == ';') {
89 if (root) {
90 root->hidden = 1;
91 }
92 break;
93 }
94
bc97a989
LM
95 /* skip spaces and tabs */
96
97 if ((*str == ' ') || (*str == '\t')) {
98 str++;
99 continue;
100 }
101
124da7fd
LM
102 /* check for open brace */
103
104 if (*str == '{') {
105 VERBOSE (DEBUG, fprintf (stdout, "start processing brace\n"));
62d56da6 106 if (root != NULL) {
124da7fd
LM
107 delelement (root);
108 return ERROR_OP;
109 }
f50ed10b 110 root = newelement (Code, 0, 5);
124da7fd
LM
111
112 do {
124da7fd
LM
113 new = parser (str + 1, &str, 0);
114 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
115 delelement (new);
116 new = ERROR_OP;
117 }
7929d368 118 if (new == ERROR_OP) {
124da7fd 119 delelement (root);
62d56da6 120 return ERROR_OP;
124da7fd 121 }
1e292005 122 element_t *newcode = newelement (Code, root->nbops + 1, 5);
8622dc12 123 for (int i = 0; i < root->nbops; i++) {
1e292005 124 newcode->ops[i] = root->ops[i];
f50ed10b 125 root->ops[i] = NULL;
124da7fd 126 }
1e292005 127 newcode->ops[root->nbops] = new;
f50ed10b 128 delelement (root);
1e292005 129 root = newcode;
124da7fd
LM
130 } while (*str == ',');
131
132 if (*str != '}') {
133 delelement (root);
134 return ERROR_OP;
135 }
136 str++;
137 VERBOSE (DEBUG, fprintf (stdout, "stop processing brace\n"));
138 continue;
139 }
140
85b4a72c 141 /* check for open bracket */
0b489a77 142
0b489a77 143 if (*str == '(') {
04d68907 144 VERBOSE (DEBUG, fprintf (stdout, "start processing bracket\n"));
0b489a77 145 if (root) {
ec3c4364
LM
146 if (root->func == Val) {
147 delelement (root);
148 return ERROR_OP;
149 }
85b4a72c
LM
150 do {
151 found = 0;
ef37d966 152 new = parser (str + 1, &str, 0);
686c4bc2 153 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
67b13e3d
LM
154 delelement (new);
155 new = ERROR_OP;
156 }
686c4bc2 157 if ((new == NULL) || (new == ERROR_OP)) {
031d7bba 158 delelement (root);
85b4a72c
LM
159 return ERROR_OP;
160 }
8622dc12 161 for (int i = 0; i < root->nbops; i++) {
85b4a72c 162 if (root->ops[i] == NULL) {
0b489a77
LM
163 root->ops[i] = new;
164 found = 1;
165 break;
166 }
167 }
85b4a72c 168 if (!found) {
031d7bba
LM
169 delelement (new);
170 delelement (root);
85b4a72c
LM
171 return ERROR_OP;
172 }
173 } while (*str == ',');
174 } else {
ec3c4364 175 root = newelement (Id, 1, 5);
ef37d966 176 new = parser (str + 1, &str, 0);
686c4bc2 177 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
67b13e3d
LM
178 delelement (new);
179 new = ERROR_OP;
180 }
686c4bc2 181 if ((new == NULL) || (new == ERROR_OP) || (*str == ',')) {
031d7bba
LM
182 delelement (new);
183 delelement (root);
efdfb543
LM
184 return ERROR_OP;
185 }
85b4a72c 186 root->ops[0] = new;
0b489a77 187 }
3c0db5bc
LM
188 if (*str != ')') {
189 delelement (root);
190 return ERROR_OP;
191 }
85b4a72c 192 str++;
04d68907 193 VERBOSE (DEBUG, fprintf (stdout, "stop processing bracket\n"));
efdfb543 194 continue;
49223129 195 }
85b4a72c 196
124da7fd 197 /* check for closing bracket, closing brace or koma */
85b4a72c 198
124da7fd 199 if ((*str == ')') || (*str == '}') || (*str == ',')) {
45a631a8
LM
200 if (prio == -9) {
201 delelement (root);
202 return ERROR_OP;
203 }
49223129 204 if (next != NULL) {
85b4a72c 205 *next = str;
49223129
LM
206 }
207 return root;
0b489a77
LM
208 }
209
bc97a989
LM
210 /* look for operators */
211
8622dc12 212 for (int i = 0; i < NB_OPERATORS; i++) {
bc97a989
LM
213 keyword_t *operator = operators + i;
214 if (codecmp (operator->keyword, str) == 0) {
04d68907 215 VERBOSE (DEBUG, fprintf (stdout, "start processing operator\n"));
a28ab26a
LM
216 if ((root) && (root->prio == 9)) {
217 VERBOSE (DEBUG, fprintf (stdout, "terminal function (%d)\n", root->func));
218 delelement (root);
219 return ERROR_OP;
220 } else if (root) {
ef37d966 221 if ((prio) && (prio > operator->prio)) {
04d68907 222 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
ef37d966
LM
223 *next = str;
224 return root;
225 }
226 str += operator->offset;
04d68907 227 VERBOSE (INFO, fprintf (stdout, "Oper: %d\n", operator->func));
d2ff8478 228 if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) {
031d7bba 229 delelement (root);
ef37d966 230 return ERROR_OP;
11cda8d7 231 }
3b4b0bbe 232 } else if (*str == '-') {
a28ab26a 233 root = newelement (Sig, 1, 6);
49223129 234 } else {
0b489a77 235 return ERROR_OP;
bc97a989 236 }
bc97a989 237 found = 1;
04d68907 238 VERBOSE (DEBUG, fprintf (stdout, "stop processing operator\n"));
bc97a989
LM
239 break;
240 }
241 }
242 if (found) {
bc97a989
LM
243 continue;
244 }
49223129 245
bc97a989
LM
246 /* look for functions */
247
8622dc12 248 for (int i = 0; i < NB_FUNCTIONS; i++) {
bc97a989
LM
249 keyword_t *function = functions + i;
250 if (codecmp (function->keyword, str) == 0) {
04d68907 251 VERBOSE (DEBUG, fprintf (stdout, "start processing function\n"));
bc97a989 252 if (root == NULL) {
04d68907 253 VERBOSE (INFO, fprintf (stdout, "Func: %d\n", function->func));
d32ea0b0 254 root = newelement (function->func, function->nbops, function->prio);
031d7bba
LM
255 } else {
256 delelement (root);
0b489a77 257 return ERROR_OP;
bc97a989
LM
258 }
259 str += function->offset;
260 found = 1;
04d68907 261 VERBOSE (DEBUG, fprintf (stdout, "stop processing function\n"));
bc97a989
LM
262 break;
263 }
264 }
265 if (found) {
bc97a989
LM
266 continue;
267 }
268
471da7c9
LM
269 /* look for constant */
270
8622dc12 271 for (int i = 0; i < NB_CONSTANTS; i++) {
471da7c9
LM
272 keyword_t *constant = constants + i;
273 if (codecmp (constant->keyword, str) == 0) {
274 VERBOSE (DEBUG, fprintf (stdout, "start processing constant\n"));
275 if (root == NULL) {
5075f6ea 276 VERBOSE (INFO, fprintf (stdout, "Const: %d\n", constant->func));
d32ea0b0 277 root = newelement (constant->func, constant->nbops, constant->prio);
471da7c9
LM
278 } else {
279 delelement (root);
280 return ERROR_OP;
281 }
282 str += constant->offset;
283 found = 1;
284 VERBOSE (DEBUG, fprintf (stdout, "stop processing constant\n"));
285 break;
286 }
287 }
288 if (found) {
289 continue;
290 }
291
bc97a989
LM
292 /* look for number */
293
20a64561
LM
294 VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
295 char *pt;
a3546d0a 296 double value = (get_ibase () == 10) ? strtod (str, &pt) : strtol (str, &pt, get_ibase ());
20a64561
LM
297 VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
298 if (str != pt) {
299 if ((root == NULL) || (root->prio == 6)) {
300 new = newelement (Val, 1, 5);
301 new->value = value;
302 if (root == NULL) {
303 root = new;
304 } else {
8622dc12 305 for (int i = 0; i < root->nbops; i++) {
20a64561
LM
306 if (root->ops[i] == NULL) {
307 root->ops[i] = new;
308 found = 1;
309 break;
ce6627f2
LM
310 }
311 }
20a64561
LM
312 if (!found) {
313 delelement (new);
031d7bba 314 delelement (root);
0b489a77 315 return ERROR_OP;
bc97a989 316 }
20a64561
LM
317 }
318 str = pt;
319 } else if ((*str == '+') || (*str == '-')) {
320 if ((prio) && (prio > 1)) {
321 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
322 *next = str;
323 return root;
324 }
325 if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) {
031d7bba 326 delelement (root);
0b9cc9b0 327 return ERROR_OP;
bc97a989 328 }
20a64561
LM
329 } else {
330 delelement (root);
331 return ERROR_OP;
bc97a989 332 }
20a64561 333 found = 1;
bc97a989 334 }
20a64561 335 VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
bc97a989
LM
336
337 /* error */
338
339 if (!found) {
031d7bba 340 delelement (root);
0b489a77 341 return ERROR_OP;
bc97a989
LM
342 }
343
344 }
345
49223129
LM
346 if (next != NULL) {
347 *next = str;
348 }
031d7bba 349
779282bb 350 /* save string */
0a8a1de3
ML
351 if (root != NULL) {
352 root->string = string;
353 }
779282bb 354
bc97a989
LM
355 return root;
356}
357
358/* print element tree */
359
360void print_element (element_t *root, int level)
361{
362 char *func = NULL;
bc97a989 363
49223129 364 if ((root == NULL) || (root == ERROR_OP)) {
bc97a989 365 return;
49223129
LM
366 }
367
8622dc12 368 for (int i = 0; i < level; i++) {
b6311fa2 369 printf (" ");
bc97a989
LM
370 }
371
372 switch (root->func) {
373 case Val: func = "Value"; break;
ec3c4364 374 case Id: func = "Ident"; break;
89cf0955 375 case Sig: func = "Sign"; break;
bc97a989
LM
376 case Add: func = "Addition"; break;
377 case Sub: func = "Subtraction"; break;
378 case Mul: func = "Multiplication"; break;
379 case Div: func = "Division"; break;
c47a9298 380 case Mod: func = "Modulo"; break;
bc97a989
LM
381 case Pow: func = "Power"; break;
382 case Sqr: func = "Square Root"; break;
383 case Cos: func = "Cosine"; break;
384 case Sin: func = "Sine"; break;
9e52bbc5
LM
385 case Tan: func = "Tangent"; break;
386 case Acos: func = "Arc Cosine"; break;
387 case Asin: func = "Arc Sine"; break;
471da7c9 388 case Atan: func = "Arc Tangent"; break;
532af887 389 case Ln: func = "Logarithm (natural)"; break;
2a986c8f 390 case Log: func = "Logarithm (10 base)"; break;
bc97a989 391 case Exp: func = "Exponantial"; break;
72b7d4bc
LM
392 case Erfc: func = "Complementary Error Function"; break;
393 case Erf: func = "Error Function"; break;
9e52bbc5
LM
394 case Abs: func = "Absolute value"; break;
395 case Ceil: func = "Ceil value"; break;
396 case Floor: func = "Floor value"; break;
6ba1dd0f
LM
397 case Store: func = "Store"; break;
398 case Recall: func = "Recall"; break;
a8cf32ba
LM
399 case Inc: func = "Increase"; break;
400 case Dec: func = "Decrease"; break;
6ba1dd0f 401 case Disp: func = "Display"; break;
eadb6e8f 402 case Memory: func = "Memory"; break;
143f91ae 403 case Clear: func = "Clear"; break;
471da7c9
LM
404 case Quit: func = "Quit"; break;
405 case Help: func = "Help"; break;
33376ef0 406 case History: func = "History"; break;
5075f6ea 407 case Ans: func = "Ans"; break;
471da7c9
LM
408 case Pi: func = "Pi"; break;
409 case E: func = "E"; break;
7fe742c9
LM
410 case Equal: func = "Equal"; break;
411 case Diff: func = "Different"; break;
412 case Ge: func = "Greater or equal"; break;
413 case Le: func = "Lesser or equal"; break;
414 case Gt: func = "Greater"; break;
415 case Lt: func = "Lesser"; break;
ca3e2a2f
LM
416 case And: func = "And"; break;
417 case Or: func = "Or"; break;
418 case Not: func = "Not"; break;
94b4e517 419 case Cond: func = "Condition"; break;
2a688642 420 case While: func = "While"; break;
05aabb97 421 case Code: func = "Code"; break;
715580ff 422 case Print: func = "Print"; break;
c7cbb833 423 case Prog: func = "Program"; break;
1e292005 424 case Arg: func = "Argument"; break;
c7cbb833
LM
425 case Call: func = "Call"; break;
426 case List: func = "List"; break;
427 case Edit: func = "Edit"; break;
428 case Del: func = "Del"; break;
a9a3da22
LM
429 case Get: func = "Get"; break;
430 case Length: func = "Length"; break;
431 case Pop: func = "Pop"; break;
432 case Push: func = "Push"; break;
433 case Put: func = "Put"; break;
434 case Set: func = "Set"; break;
435 case Show: func = "Show"; break;
226557a3
LM
436 case Max: func = "Maximum"; break;
437 case Mean: func = "Mean"; break;
438 case Median: func = "Median"; break;
439 case Min: func = "Minimum"; break;
440 case Order: func = "Order"; break;
441 case Prod: func = "Product"; break;
442 case Sum: func = "Sum"; break;
443 case Variance: func = "Variance"; break;
e2a309f9 444 case Precision: func = "Precision"; break;
743e93f0 445 case Base: func = "Base"; break;
807bdeba
LM
446 case Deg: func = "Degree"; break;
447 case Grad: func = "Gradian"; break;
448 case Rad: func = "Radian"; break;
bc97a989
LM
449 }
450
b6311fa2 451 printf ("Function: %s\n", func);
bc97a989 452
85b4a72c 453 if ((root->func == Val) && (root->ops[0] == NULL)) {
8622dc12 454 for (int i = 0; i < level; i++) {
b6311fa2 455 printf (" ");
bc97a989 456 }
b6311fa2 457 printf ("value: %f\n", root->value);
bc97a989 458 } else {
8622dc12 459 for (int i = 0; i < root->nbops; i++) {
bc97a989
LM
460 print_element (root->ops[i], level + 1);
461 }
462 }
463}
464
2a688642
LM
465/* While do function */
466
467double while_do (element_t *cond, element_t *action)
468{
469 double ret = 0;
470 element_t *temp = NULL;
471
472 VERBOSE (DEBUG, fprintf (stdout, "starting while loop\n"));
2a688642
LM
473 while (1) {
474 VERBOSE (DEBUG, fprintf (stdout, "loop...\n"));
475
476 temp = dupelement (cond);
523841a1
ML
477 double test = evaluate_element (temp, 0);
478 delelement (temp);
479 if (!test) {
2a688642
LM
480 break;
481 }
482 if (action) {
483 temp = dupelement (action);
484 ret = evaluate_element (temp, 0);
523841a1 485 delelement (temp);
2a688642
LM
486 }
487 }
488
489 VERBOSE (DEBUG, fprintf (stdout, "ending while loop\n"));
490
491 return ret;
492}
493
124da7fd
LM
494/* program function */
495
05aabb97 496double execute_code (element_t **prog, int nbcalls)
124da7fd
LM
497{
498 double ret = 0;
8622dc12 499 for (int i = 0; i < nbcalls; i++) {
124da7fd 500 ret = evaluate_element (prog[i], 0);
124da7fd
LM
501 }
502 return ret;
503}
504
89cf0955
LM
505/* quit function */
506
507void quit (void)
508{
b6311fa2 509 printf ("bye\n");
89cf0955
LM
510 exit (0);
511}
512
513/* help message */
514
515void help (void)
516{
b6311fa2
LM
517 printf ("calc is a simple calculator\n\n");
518 printf ("arithmetic op.:");
519 printf (" + - * / %% ^\n");
520 printf ("comparison op.:");
521 printf (" == != >= <= > <\n");
522 printf ("logical op.:");
523 printf (" & | !\n");
524 printf ("mathematic func.:");
525 printf (" exp ln log pow sqrt\n");
526 printf ("trigonometric func.:");
527 printf (" acos asin atan cos sin tan\n");
528 printf ("error functions:");
529 printf (" erf erfc\n");
530 printf ("miscellaneous func.:");
531 printf (" abs ceil floor\n");
532 printf ("storage func.:");
533 printf (" clear dec disp inc mem rcl sto\n");
534 printf ("control flow prim.:");
535 printf (" cond print while {} ;\n");
536 printf ("program management:");
537 printf (" arg call del edit ls prog\n");
538 printf ("stack management:");
539 printf (" get len pop push put set show\n");
540 printf ("stack func.:");
541 printf (" max mean med min ord prod sum var\n");
542 printf ("control management:");
33376ef0
LM
543 printf (" base format help hist quit\n");
544 printf ("angle management:");
545 printf (" deg grad rad\n");
b6311fa2
LM
546 printf ("constants:");
547 printf (" ans e pi\n");
89cf0955 548}
3b4b0bbe 549
743e93f0
LM
550/* format function */
551
552int format (int precision)
553{
554 if (precision > 0) {
555 set_precision (precision);
556 set_format ();
557 } else if (precision != -1) {
558 VERBOSE (WARNING, fprintf (stdout, "error incorrect precision (%d)\n", precision));
559 return 0;
560 }
561 return get_precision ();
562}
563
564/* base function */
565
566void base (int in, int out)
567{
0b69fdfb 568 if ((in > 0) && (in < 37)) {
743e93f0 569 set_base (in, in);
0b69fdfb 570 if ((out > 0) && (out < 37)) {
743e93f0
LM
571 set_base (in, out);
572 } else if (out != - 1) {
573 VERBOSE (WARNING, fprintf (stdout, "error incorrect output base (%d)\n", out));
574 }
575 } else if (in != -1 ) {
576 VERBOSE (WARNING, fprintf (stdout, "error incorrect input base (%d)\n", in));
577 } else {
578 printf ("base (I/O): %s\n", show_base ());
579 }
580}
581
f2927108
LM
582/* evaluate element tree */
583
89cf0955
LM
584#define MASK_SUB 0x1
585#define MASK_DIV 0x2
586
3b4b0bbe 587double evaluate_element (element_t *root, char mask)
f2927108
LM
588{
589 double op0 = 0, op1 = 0;
3b4b0bbe 590 char nextmask = mask;
e7d5c144 591 int i, nb;
f2927108
LM
592
593 if ((root == NULL) || (root == ERROR_OP)) {
04d68907 594 VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n"));
f2927108
LM
595 return 0;
596 }
597
3b4b0bbe
LM
598 /* mask to manage sub operator sub and div */
599 switch (root->func) {
600 case Add:
601 nextmask &= ~MASK_SUB;
602 nextmask &= ~MASK_DIV;
603 break;
604 case Sub:
605 nextmask |= MASK_SUB;
606 nextmask &= ~MASK_DIV;
607 break;
608 case Mul:
609 nextmask &= ~MASK_DIV;
610 break;
611 case Div:
612 nextmask |= MASK_DIV;
613 break;
614 default:
615 nextmask = mask;
616 }
617
f2927108
LM
618 switch (root->func) {
619 case Val:
3b4b0bbe
LM
620 case Sig:
621 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
f2927108
LM
622 break;
623 case Add:
624 case Sub:
625 case Mul:
626 case Div:
c47a9298 627 case Mod:
f2927108 628 case Pow:
7fe742c9
LM
629 case Equal:
630 case Diff:
631 case Ge:
632 case Le:
633 case Gt:
634 case Lt:
ca3e2a2f
LM
635 case And:
636 case Or:
f2927108 637 if (root->ops[1]) {
3b4b0bbe 638 op1 = evaluate_element (root->ops[1], nextmask);
eadb6e8f 639 } else {
04d68907 640 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
f2927108
LM
641 return 0;
642 }
643 /* fallthrough */
ec3c4364 644 case Id:
f2927108
LM
645 case Sqr:
646 case Cos:
647 case Sin:
9e52bbc5
LM
648 case Tan:
649 case Acos:
650 case Asin:
471da7c9 651 case Atan:
2a986c8f 652 case Ln:
f2927108
LM
653 case Log:
654 case Exp:
72b7d4bc
LM
655 case Erfc:
656 case Erf:
9e52bbc5
LM
657 case Abs:
658 case Ceil:
659 case Floor:
6ba1dd0f 660 case Recall:
a8cf32ba
LM
661 case Inc:
662 case Dec:
ca3e2a2f 663 case Not:
94b4e517 664 case Cond:
1e292005
LM
665 case Prog:
666 case Arg:
c7cbb833 667 case Call:
c7cbb833
LM
668 case Edit:
669 case Del:
a9a3da22 670 case Get:
f2927108 671 if (root->ops[0]) {
3b4b0bbe 672 op0 = evaluate_element (root->ops[0], 0);
f2927108 673 } else {
04d68907 674 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
f2927108
LM
675 return 0;
676 }
89cf0955 677 break;
6ba1dd0f 678 case Disp:
143f91ae 679 case Clear:
471da7c9
LM
680 case Quit:
681 case Help:
33376ef0 682 case History:
5075f6ea 683 case Ans:
471da7c9
LM
684 case Pi:
685 case E:
05aabb97 686 case Code:
e7d5c144 687 case List:
a9a3da22
LM
688 case Length:
689 case Pop:
690 case Set:
691 case Show:
226557a3
LM
692 case Median:
693 case Order:
694 case Prod:
695 case Sum:
807bdeba
LM
696 case Deg:
697 case Grad:
698 case Rad:
09d87cae 699 break;
2a688642 700 case While:
09d87cae
LM
701 if (root->ops[0] == NULL) {
702 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
703 return 0;
704 }
89cf0955 705 break;
eadb6e8f
LM
706 case Memory:
707 if (root->ops[0] == NULL) {
708 op0 = -1;
709 } else {
710 op0 = (int)evaluate_element (root->ops[0], 0);
711 if (op0 < 0) {
712 VERBOSE (WARNING, fprintf (stdout, "error incorrect memory size (%d)\n", (int)op0));
713 return 0;
714 }
715 }
716 break;
a9a3da22 717 case Push:
715580ff
LM
718 case Print:
719 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
720 break;
eadb6e8f 721 case Store:
a9a3da22
LM
722 case Put:
723 if (root->ops[0]) {
724 op0 = evaluate_element (root->ops[0], 0);
725 } else {
726 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
727 return 0;
728 }
729 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
730 break;
226557a3
LM
731 case Max:
732 case Mean:
733 case Min:
734 case Variance:
735 if (root->ops[0]) {
736 op0 = evaluate_element (root->ops[0], 0);
737 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
738 }
e2a309f9
LM
739 break;
740 case Precision:
741 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : -1;
742 break;
743e93f0
LM
743 case Base:
744 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : -1;
745 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : -1;
746 break;
f2927108
LM
747 }
748
749 switch (root->func) {
3b4b0bbe 750 case Val: return op0;
ec3c4364 751 case Id: return op0;
3b4b0bbe
LM
752 case Sig: return -op0;
753 case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1;
754 case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1;
755 case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1;
756 case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1;
c47a9298 757 case Mod: return fmod (op0, op1);
f2927108
LM
758 case Pow: return pow (op0, op1);
759 case Sqr: return sqrt (op0);
807bdeba
LM
760 case Cos: return cos (op0 / anglefactor);
761 case Sin: return sin (op0 / anglefactor);
762 case Tan: return tan (op0 / anglefactor);
763 case Acos: return acos (op0) * anglefactor;
764 case Asin: return asin (op0) * anglefactor;
765 case Atan: return atan (op0) * anglefactor;
2a986c8f
LM
766 case Ln: return log (op0);
767 case Log: return log10 (op0);
f2927108 768 case Exp: return exp (op0);
72b7d4bc
LM
769 case Erfc: return erfc (op0);
770 case Erf: return erf (op0);
9e52bbc5
LM
771 case Abs: return fabs (op0);
772 case Ceil: return ceil (op0);
773 case Floor: return floor (op0);
eadb6e8f 774 case Store: return store ((int)op0, op1);
6ba1dd0f 775 case Recall: return recall ((int)op0);
a8cf32ba
LM
776 case Inc: return increase ((int)op0);
777 case Dec: return decrease ((int)op0);
6ba1dd0f 778 case Disp: display (); break;
eadb6e8f 779 case Memory: return memory ((root->ops[0]) ? (int)op0 : -1);
143f91ae 780 case Clear: clear (); break;
471da7c9
LM
781 case Quit: quit (); break;
782 case Help: help (); break;
33376ef0 783 case History: history (); break;
5075f6ea 784 case Ans: return answer;
471da7c9
LM
785 case Pi: return M_PI;
786 case E: return M_E;
7fe742c9
LM
787 case Equal: return op0 == op1;
788 case Diff: return op0 != op1;
789 case Ge: return op0 >= op1;
790 case Le: return op0 <= op1;
791 case Gt: return op0 > op1;
792 case Lt: return op0 < op1;
ca3e2a2f
LM
793 case And: return (op0 != 0) && (op1 != 0);
794 case Or: return (op0 != 0) || (op1 != 0);
795 case Not: return (op0 == 0);
94b4e517
LM
796 case Cond:
797 if ((op0) && (root->ops[1])) {
798 return evaluate_element (root->ops[1], 0);
799 } else if ((!op0) && (root->ops[2])) {
800 return evaluate_element (root->ops[2], 0);
801 } else {
802 return 0;
803 }
2a688642 804 case While: return while_do (root->ops[0], root->ops[1]);
05aabb97 805 case Code: return execute_code (root->ops, root->nbops);
2a5ec9d1 806 case Print: return print (op0);
779282bb 807 case Prog:
1e292005 808 prog ((int)op0, root->ops[1]);
779282bb
LM
809 savestring ((int)op0, root->string);
810 break;
1e292005 811 case Arg: return arg ((int)op0);
e7d5c144 812 case Call:
2ddb38f0 813 for (i = 1, nb = 0; i < root->nbops; i++) {
e7d5c144
LM
814 if (root->ops[i]) {
815 nb++;
816 }
817 }
818 return call ((int)op0, nb, root->ops + 1);
c7cbb833
LM
819 case List: list (); break;
820 case Edit: edit ((int)op0); break;
05aabb97 821 case Del: del ((int)op0); break;
a9a3da22
LM
822 case Get: return get ((int)op0);
823 case Length: return length ();
824 case Pop: return pop ();
825 case Push: return push (op0);
826 case Put: return put ((int)op0, op1);
827 case Set:
828 for (i = 0, nb =0; i < root->nbops; i++) {
829 if (root->ops[i]) {
830 nb++;
831 }
832 }
833 return set (nb, root->ops);
834 case Show: show (); break;
226557a3
LM
835 case Max:
836 if (root->ops[0]) {
837 return op0 > op1 ? op0 : op1;
838 }
839 return max ();
840 case Mean:
841 if (root->ops[0]) {
842 return (op0 + op1) / 2;
843 }
844 return mean ();
845 case Median: return median ();
846 case Min:
847 if (root->ops[0]) {
848 return op0 < op1 ? op0 : op1;
849 }
850 return min ();
851 case Order: order (); break;
852 case Prod: return prod ();
853 case Sum: return sum ();
854 case Variance:
855 if (root->ops[0]) {
856 double m = (op0 + op1) / 2;
857 op0 -= m;
858 op1 -= m;
859 return op0 * op0 + op1 * op1;
860 }
861 return variance ();
e2a309f9 862 case Precision:
743e93f0
LM
863 return format ((int)op0);
864 case Base:
0b69fdfb 865 base ((int)op0, (int)op1);
743e93f0 866 break;
807bdeba
LM
867 case Deg:
868 anglefactor = 180 / M_PI;
869 break;
870 case Grad:
871 anglefactor = 200 / M_PI;
872 break;
873 case Rad:
874 anglefactor = 1;
875 break;
f2927108
LM
876 }
877
878 return 0;
879}
880
bc97a989 881/* vim: set ts=4 sw=4 et: */