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