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