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