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