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