clean some tests
[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 double *storage = NULL;
18
19 int argument_size = 0;
20 double *argument = NULL;
21
22 int stack_size = 0;
23 double *stack = NULL;
24
25 #define DEFAULT_FORMAT "=> %.6g\n"
26 char *format = NULL;
27 char *minform = NULL;
28
29 workspace_t *programs = NULL;
30 int nb_programs = 0;
31
32 /* compare codes */
33
34 int codecmp (char *ref, char *str)
35 {
36 int sig;
37
38 while (*ref != '\0') {
39 if (*ref == '\t') {
40 sig = (*str == '.') ? -1 : ((*str >= '0') && (*str <= '9'));
41 } else {
42 sig = *str - *ref;
43 }
44 if (sig != 0) {
45 return (sig > 0) ? 1 : -1;
46 }
47 str++;
48 ref++;
49 }
50
51 return 0;
52 }
53
54 /* calloc or die function */
55
56 void *callocordie (size_t count, size_t size)
57 {
58 if (count * size == 0) {
59 return NULL;
60 }
61 void *new = calloc (count, size);
62 if (new == NULL) {
63 VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n"));
64 exit (1);
65 }
66 return new;
67 }
68
69 /* allocate new element */
70
71 element_t *newelement (func_t function, int nbops, int prio)
72 {
73 element_t *new = (element_t *) callocordie (1, sizeof (element_t));
74 if (nbops) {
75 new->ops = (element_t **) callocordie (nbops, sizeof (element_t *));
76 }
77 new->func = function;
78 new->nbops = nbops;
79 new->prio = prio;
80
81 return new;
82 }
83
84 /* desallocate element */
85
86 void delelement (element_t *root)
87 {
88 if ((root != NULL) && (root != ERROR_OP)) {
89 int i;
90 for (i = 0; i < root->nbops; i++) {
91 delelement (root->ops[i]);
92 }
93 if (root->nbops) {
94 free (root->ops);
95 }
96 free (root);
97 }
98 }
99
100 /* duplicate element */
101
102 element_t *dupelement (element_t *root)
103 {
104 element_t *tmp = NULL;
105 int i;
106
107 if ((root == NULL) || (root == ERROR_OP)) {
108 return root;
109 }
110 tmp = newelement (root->func, root->nbops, root->prio);
111 tmp->value = root->value;
112 for (i = 0; i < root->nbops; i++) {
113 tmp->ops[i] = dupelement (root->ops[i]);
114 }
115 return tmp;
116 }
117
118 /* functions */
119
120 #define MAX_ARGS 100
121
122 #define NB_OPERATORS 14
123 keyword_t operators[NB_OPERATORS] = {
124 { "+\t", Add, 2, 1, 1},
125 { "-\t", Sub, 2, 1, 1},
126 { "*", Mul, 2, 1, 2},
127 { "/", Div, 2, 1, 2},
128 { "%", Mod, 2, 1, 3},
129 { "^", Pow, 2, 1, 4},
130 { "==", Equal, 2, 2, -1},
131 { "!=", Diff, 2, 2, -1},
132 { ">=", Ge, 2, 2, -1},
133 { "<=", Le, 2, 2, -1},
134 { ">", Gt, 2, 1, -1},
135 { "<", Lt, 2, 1, -1},
136 { "&", And, 2, 1, -2},
137 { "|", Or, 2, 1, -2}
138 };
139
140 #define NB_FUNCTIONS 50
141 keyword_t functions[NB_FUNCTIONS] = {
142 { "sqrt", Sqr, 1, 4, 5},
143 { "pow", Pow, 2, 3, 5},
144 { "cos", Cos, 1, 3, 5},
145 { "sin", Sin, 1, 3, 5},
146 { "tan", Tan, 1, 3, 5},
147 { "acos", Acos, 1, 4, 5},
148 { "asin", Asin, 1, 4, 5},
149 { "atan", Atan, 1, 4, 5},
150 { "ln", Ln, 1, 2, 5},
151 { "log", Log, 1, 3, 5},
152 { "exp", Exp, 1, 3, 5},
153 { "erfc", Erfc, 1, 4, 5},
154 { "erf", Erf, 1, 3, 5},
155 { "abs", Abs, 1, 3, 5},
156 { "floor", Floor, 1, 5, 5},
157 { "ceil", Ceil, 1, 4, 5},
158 { "sto", Store, 2, 3, 5},
159 { "rcl", Recall, 1, 3, 5},
160 { "inc", Inc, 1, 3, 5},
161 { "dec", Dec, 1, 3, 5},
162 { "disp", Disp, 0, 4, 9},
163 { "mem", Mem, 1, 3, 5},
164 { "clr", Clear, 0, 3, 9},
165 { "quit", Quit, 0, 4, 9},
166 { "help", Help, 0, 4, 9},
167 { "!", Not, 1, 1, 6},
168 { "cond", Cond, 3, 4, 5},
169 { "while", While, 2, 5, 5},
170 { "print", Print, 1, 5, 5},
171 { "prog", Prog, 2, 4, 9},
172 { "arg", Arg, 1, 3, 5},
173 { "call", Call, MAX_ARGS, 4, 5},
174 { "ls", List, 0, 2, 9},
175 { "edit", Edit, 1, 4, 9},
176 { "del", Del, 1, 3, 9},
177 { "get", Get, 1, 3, 5},
178 { "len", Length, 0, 3, 5},
179 { "pop", Pop, 0, 3, 5},
180 { "push", Push, 1, 4, 5},
181 { "put", Put, 2, 3, 5},
182 { "set", Set, MAX_ARGS, 3, 5},
183 { "show", Show, 0, 4, 5},
184 { "max", Max, 2, 3, 5},
185 { "mean", Mean, 2, 4, 5},
186 { "med", Median, 0, 3, 5},
187 { "min", Min, 2, 3, 5},
188 { "ord", Order, 0, 3, 5},
189 { "prod", Prod, 0, 4, 5},
190 { "sum", Sum, 0, 3, 5},
191 { "var", Variance, 2, 3, 5},
192 };
193
194 #define NB_CONSTANTS 3
195 keyword_t constants[NB_CONSTANTS] = {
196 { "ans", Ans, 0, 3, 5},
197 { "e", E, 0, 1, 5},
198 { "pi", Pi, 0, 2, 5}
199 };
200
201 #define NB_SYMBOLS 4
202 char *symbols[NB_SYMBOLS] = {
203 "(", ")", "{", "}"
204 };
205
206 /* subparser function */
207
208 element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, int prio)
209 {
210 element_t *new = newelement (func, nbops, prio);
211 new->ops[0] = *proot;
212 new->ops[1] = parser (*pstr, pstr, new->prio);
213 if ((new->ops[1] == NULL) || ((new->ops[1] != ERROR_OP) && (new->ops[1]->prio == 9))) {
214 delelement (new->ops[1]);
215 new->ops[1] = ERROR_OP;
216 }
217 if (new->ops[1] == ERROR_OP) {
218 delelement (new);
219 *proot = NULL;
220 return ERROR_OP;
221 }
222 *proot = newelement (Val, 1, 5);
223 (*proot)->ops[0] = new;
224
225 return *proot;
226 }
227
228 /* parser function */
229
230 element_t *parser (char *str, char **next, int prio)
231 {
232 element_t *root = NULL;
233 char *string = str;
234 int i;
235
236 VERBOSE (DEBUG, fprintf (stdout, "Starting parsing\n"));
237
238 /* main loop */
239 while (*str != '\0') {
240 int found = 0;
241 element_t *new = NULL;
242 VERBOSE (INFO, fprintf (stdout, "Processing: %s\n", str));
243
244 /* end without printing */
245
246 if (*str == ';') {
247 if (root) {
248 root->hidden = 1;
249 }
250 break;
251 }
252
253 /* skip spaces and tabs */
254
255 if ((*str == ' ') || (*str == '\t')) {
256 str++;
257 continue;
258 }
259
260 /* check for open brace */
261
262 if (*str == '{') {
263 VERBOSE (DEBUG, fprintf (stdout, "start processing brace\n"));
264 if (root != NULL) {
265 delelement (root);
266 return ERROR_OP;
267 }
268 root = newelement (Code, 0, 5);
269
270 do {
271 new = parser (str + 1, &str, 0);
272 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
273 delelement (new);
274 new = ERROR_OP;
275 }
276 if (new == ERROR_OP) {
277 delelement (root);
278 return ERROR_OP;
279 }
280 element_t *newcode = newelement (Code, root->nbops + 1, 5);
281 for (i = 0; i < root->nbops; i++) {
282 newcode->ops[i] = root->ops[i];
283 root->ops[i] = NULL;
284 }
285 newcode->ops[root->nbops] = new;
286 delelement (root);
287 root = newcode;
288 } while (*str == ',');
289
290 if (*str != '}') {
291 delelement (root);
292 return ERROR_OP;
293 }
294 str++;
295 VERBOSE (DEBUG, fprintf (stdout, "stop processing brace\n"));
296 continue;
297 }
298
299 /* check for open bracket */
300
301 if (*str == '(') {
302 VERBOSE (DEBUG, fprintf (stdout, "start processing bracket\n"));
303 if (root) {
304 do {
305 found = 0;
306 new = parser (str + 1, &str, 0);
307 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
308 delelement (new);
309 new = ERROR_OP;
310 }
311 if ((new == NULL) || (new == ERROR_OP)) {
312 delelement (root);
313 return ERROR_OP;
314 }
315 for (i = 0; i < root->nbops; i++) {
316 if (root->ops[i] == NULL) {
317 root->ops[i] = new;
318 found = 1;
319 break;
320 }
321 }
322 if (!found) {
323 delelement (new);
324 delelement (root);
325 return ERROR_OP;
326 }
327 } while (*str == ',');
328 } else {
329 root = newelement (Val, 1, 5);
330 new = parser (str + 1, &str, 0);
331 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
332 delelement (new);
333 new = ERROR_OP;
334 }
335 if ((new == NULL) || (new == ERROR_OP) || (*str == ',')) {
336 delelement (new);
337 delelement (root);
338 return ERROR_OP;
339 }
340 root->ops[0] = new;
341 }
342 if (*str != ')') {
343 delelement (root);
344 return ERROR_OP;
345 }
346 str++;
347 VERBOSE (DEBUG, fprintf (stdout, "stop processing bracket\n"));
348 continue;
349 }
350
351 /* check for closing bracket, closing brace or koma */
352
353 if ((*str == ')') || (*str == '}') || (*str == ',')) {
354 if (prio == -9) {
355 delelement (root);
356 return ERROR_OP;
357 }
358 if (next != NULL) {
359 *next = str;
360 }
361 return root;
362 }
363
364 /* look for operators */
365
366 for (i = 0; i < NB_OPERATORS; i++) {
367 keyword_t *operator = operators + i;
368 if (codecmp (operator->keyword, str) == 0) {
369 VERBOSE (DEBUG, fprintf (stdout, "start processing operator\n"));
370 if ((root) && (root->prio == 9)) {
371 VERBOSE (DEBUG, fprintf (stdout, "terminal function (%d)\n", root->func));
372 delelement (root);
373 return ERROR_OP;
374 } else if (root) {
375 if ((prio) && (prio > operator->prio)) {
376 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
377 *next = str;
378 return root;
379 }
380 str += operator->offset;
381 VERBOSE (INFO, fprintf (stdout, "Oper: %d\n", operator->func));
382 if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) {
383 delelement (root);
384 return ERROR_OP;
385 }
386 } else if (*str == '-') {
387 root = newelement (Sig, 1, 6);
388 } else {
389 return ERROR_OP;
390 }
391 found = 1;
392 VERBOSE (DEBUG, fprintf (stdout, "stop processing operator\n"));
393 break;
394 }
395 }
396 if (found) {
397 continue;
398 }
399
400 /* look for functions */
401
402 for (i = 0; i < NB_FUNCTIONS; i++) {
403 keyword_t *function = functions + i;
404 if (codecmp (function->keyword, str) == 0) {
405 VERBOSE (DEBUG, fprintf (stdout, "start processing function\n"));
406 if (root == NULL) {
407 VERBOSE (INFO, fprintf (stdout, "Func: %d\n", function->func));
408 root = newelement (function->func, function->nbops, function->prio);
409 } else {
410 delelement (root);
411 return ERROR_OP;
412 }
413 str += function->offset;
414 found = 1;
415 VERBOSE (DEBUG, fprintf (stdout, "stop processing function\n"));
416 break;
417 }
418 }
419 if (found) {
420 continue;
421 }
422
423 /* look for constant */
424
425 for (i = 0; i < NB_CONSTANTS; i++) {
426 keyword_t *constant = constants + i;
427 if (codecmp (constant->keyword, str) == 0) {
428 VERBOSE (DEBUG, fprintf (stdout, "start processing constant\n"));
429 if (root == NULL) {
430 VERBOSE (INFO, fprintf (stdout, "Const: %d\n", constant->func));
431 root = newelement (constant->func, constant->nbops, constant->prio);
432 } else {
433 delelement (root);
434 return ERROR_OP;
435 }
436 str += constant->offset;
437 found = 1;
438 VERBOSE (DEBUG, fprintf (stdout, "stop processing constant\n"));
439 break;
440 }
441 }
442 if (found) {
443 continue;
444 }
445
446 /* look for number */
447
448 if (((*str >= '0') && (*str <= '9')) ||
449 (*str == '.') || (*str == '+') || (*str == '-')) {
450 VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
451 char *pt;
452 double value = strtod (str, &pt);
453 VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
454 if (str != pt) {
455 if ((root == NULL) || (root->prio == 6)) {
456 new = newelement (Val, 1, 5);
457 new->value = value;
458 if (root == NULL) {
459 root = new;
460 } else {
461 for (i = 0; i < root->nbops; i++) {
462 if (root->ops[i] == NULL) {
463 root->ops[i] = new;
464 found = 1;
465 break;
466 }
467 }
468 if (!found) {
469 delelement (new);
470 delelement (root);
471 return ERROR_OP;
472 }
473 }
474 str = pt;
475 } else if ((*str == '+') || (*str == '-')) {
476 if ((prio) && (prio > 1)) {
477 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
478 *next = str;
479 return root;
480 }
481 if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) {
482 delelement (root);
483 return ERROR_OP;
484 }
485 } else {
486 delelement (root);
487 return ERROR_OP;
488 }
489 found = 1;
490 }
491 VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
492 }
493
494 /* error */
495
496 if (!found) {
497 delelement (root);
498 return ERROR_OP;
499 }
500
501 }
502
503 if (next != NULL) {
504 *next = str;
505 }
506
507 /* save string */
508 if (root != NULL) {
509 root->string = string;
510 }
511
512 return root;
513 }
514
515 /* print element tree */
516
517 void print_element (element_t *root, int level)
518 {
519 char *func = NULL;
520 int i;
521
522 if ((root == NULL) || (root == ERROR_OP)) {
523 return;
524 }
525
526 for (i = 0; i < level; i++) {
527 fprintf (stdout, " ");
528 }
529
530 switch (root->func) {
531 case Val: func = "Value"; break;
532 case Sig: func = "Sign"; break;
533 case Add: func = "Addition"; break;
534 case Sub: func = "Subtraction"; break;
535 case Mul: func = "Multiplication"; break;
536 case Div: func = "Division"; break;
537 case Mod: func = "Modulo"; break;
538 case Pow: func = "Power"; break;
539 case Sqr: func = "Square Root"; break;
540 case Cos: func = "Cosine"; break;
541 case Sin: func = "Sine"; break;
542 case Tan: func = "Tangent"; break;
543 case Acos: func = "Arc Cosine"; break;
544 case Asin: func = "Arc Sine"; break;
545 case Atan: func = "Arc Tangent"; break;
546 case Ln: func = "Logarithm (natural)"; break;
547 case Log: func = "Logarithm (10 base)"; break;
548 case Exp: func = "Exponantial"; break;
549 case Erfc: func = "Complementary Error Function"; break;
550 case Erf: func = "Error Function"; break;
551 case Abs: func = "Absolute value"; break;
552 case Ceil: func = "Ceil value"; break;
553 case Floor: func = "Floor value"; break;
554 case Store: func = "Store"; break;
555 case Recall: func = "Recall"; break;
556 case Inc: func = "Increase"; break;
557 case Dec: func = "Decrease"; break;
558 case Disp: func = "Display"; break;
559 case Mem: func = "Memory"; break;
560 case Clear: func = "Clear"; break;
561 case Quit: func = "Quit"; break;
562 case Help: func = "Help"; break;
563 case Ans: func = "Ans"; break;
564 case Pi: func = "Pi"; break;
565 case E: func = "E"; break;
566 case Equal: func = "Equal"; break;
567 case Diff: func = "Different"; break;
568 case Ge: func = "Greater or equal"; break;
569 case Le: func = "Lesser or equal"; break;
570 case Gt: func = "Greater"; break;
571 case Lt: func = "Lesser"; break;
572 case And: func = "And"; break;
573 case Or: func = "Or"; break;
574 case Not: func = "Not"; break;
575 case Cond: func = "Condition"; break;
576 case While: func = "While"; break;
577 case Code: func = "Code"; break;
578 case Print: func = "Print"; break;
579 case Prog: func = "Program"; break;
580 case Arg: func = "Argument"; break;
581 case Call: func = "Call"; break;
582 case List: func = "List"; break;
583 case Edit: func = "Edit"; break;
584 case Del: func = "Del"; break;
585 case Get: func = "Get"; break;
586 case Length: func = "Length"; break;
587 case Pop: func = "Pop"; break;
588 case Push: func = "Push"; break;
589 case Put: func = "Put"; break;
590 case Set: func = "Set"; break;
591 case Show: func = "Show"; break;
592 case Max: func = "Maximum"; break;
593 case Mean: func = "Mean"; break;
594 case Median: func = "Median"; break;
595 case Min: func = "Minimum"; break;
596 case Order: func = "Order"; break;
597 case Prod: func = "Product"; break;
598 case Sum: func = "Sum"; break;
599 case Variance: func = "Variance"; break;
600 }
601
602 fprintf (stdout, "Function: %s\n", func);
603
604 if ((root->func == Val) && (root->ops[0] == NULL)) {
605 for (i = 0; i < level; i++) {
606 fprintf (stdout, " ");
607 }
608 fprintf (stdout, "value: %f\n", root->value);
609 } else {
610 for (i = 0; i < root->nbops; i++) {
611 print_element (root->ops[i], level + 1);
612 }
613 }
614 }
615
616 /* storage functions */
617
618 void memory (int nb)
619 {
620 int i, l;
621 double *tmp = NULL;
622 if (nb != storage_size) {
623 l = (nb < storage_size) ? nb : storage_size;
624 tmp = (double *) callocordie (nb, sizeof (double));
625 for (i = 0; i < l; i++) {
626 tmp[i] = storage[i];
627 }
628 if (storage != NULL) {
629 free (storage);
630 }
631 storage = tmp;
632 storage_size = nb;
633 }
634 }
635
636 double store (int index, double value)
637 {
638 if (storage_size == -1) {
639 memory (DEFAULT_STORAGE_SIZE);
640 }
641 if ((index > 0) && (index <= storage_size)) {
642 storage[index - 1] = value;
643 } else {
644 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
645 }
646 return value;
647 }
648
649 double recall (int index)
650 {
651 if (storage_size == -1) {
652 memory (DEFAULT_STORAGE_SIZE);
653 }
654 if ((index > 0) && (index <= storage_size)) {
655 return storage[index - 1];
656 } else {
657 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
658 }
659 return 0;
660 }
661
662 double increase (int index)
663 {
664 if (storage_size == -1) {
665 memory (DEFAULT_STORAGE_SIZE);
666 }
667 if ((index > 0) && (index <= storage_size)) {
668 return storage[index - 1]++;
669 } else {
670 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
671 }
672 return 0;
673 }
674
675 double decrease (int index)
676 {
677 if (storage_size == -1) {
678 memory (DEFAULT_STORAGE_SIZE);
679 }
680 if ((index > 0) && (index <= storage_size)) {
681 return storage[index - 1]--;
682 } else {
683 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
684 }
685 return 0;
686 }
687
688 void display (void)
689 {
690 int i;
691 if (storage_size == -1) {
692 memory (DEFAULT_STORAGE_SIZE);
693 }
694 fprintf (stdout, "storage:");
695 for (i = 0; i < storage_size; i++) {
696 fprintf (stdout, " ");
697 fprintf (stdout, minform, storage[i]);
698 }
699 fprintf (stdout, "\n");
700 }
701
702 void clear ()
703 {
704 int i;
705 for (i = 0; i < storage_size; i++) {
706 storage[i] = 0;
707 }
708 }
709
710 /* While do function */
711
712 double while_do (element_t *cond, element_t *action)
713 {
714 double ret = 0;
715 element_t *temp = NULL;
716
717 VERBOSE (DEBUG, fprintf (stdout, "starting while loop\n"));
718 while (1) {
719 VERBOSE (DEBUG, fprintf (stdout, "loop...\n"));
720
721 temp = dupelement (cond);
722 double test = evaluate_element (temp, 0);
723 delelement (temp);
724 if (!test) {
725 break;
726 }
727 if (action) {
728 temp = dupelement (action);
729 ret = evaluate_element (temp, 0);
730 delelement (temp);
731 }
732 }
733
734 VERBOSE (DEBUG, fprintf (stdout, "ending while loop\n"));
735
736 return ret;
737 }
738
739 /* program function */
740
741 double execute_code (element_t **prog, int nbcalls)
742 {
743 double ret = 0;
744 int i;
745 for (i = 0; i < nbcalls; i++) {
746 ret = evaluate_element (prog[i], 0);
747 }
748 return ret;
749 }
750
751 /* print function */
752
753 void set_format (char *prompt, int precision)
754 {
755 char buffer[128] = {0};
756 free_format ();
757 sprintf (buffer, "%s%%.%dg\n", prompt, precision);
758 format = strdup (buffer);
759 sprintf (buffer, "%%.%dg", precision);
760 minform = strdup (buffer);
761 }
762
763 void free_format ()
764 {
765 if (format) {
766 free (format);
767 format = NULL;
768 }
769 if (minform) {
770 free (minform);
771 minform = NULL;
772 }
773 }
774
775 double print (double value)
776 {
777 fprintf (stdout, format ? format : DEFAULT_FORMAT, value);
778 fflush (stdout);
779 return value;
780 }
781
782 /* quit function */
783
784 void quit (void)
785 {
786 fprintf (stdout, "bye\n");
787 exit (0);
788 }
789
790 /* program function */
791
792 void prog (int id, element_t *root)
793 {
794 int i, n = -1;
795
796 if (programs == NULL) {
797
798 /* initial memory allocation */
799 programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
800 nb_programs = 1;
801 n = 0;
802
803 } else {
804
805 /* look for existing program */
806 for (i = 0; i < nb_programs; i++) {
807 if ((programs + i)->id == id) {
808 n = i;
809 break;
810 }
811 }
812 if (n == -1) {
813
814 /* new program */
815 n = nb_programs++;
816 workspace_t *tmp = (workspace_t *) callocordie (nb_programs, sizeof (workspace_t));
817 memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t));
818 free (programs);
819 programs = tmp;
820 } else {
821
822 /* clean old program */
823 if ((programs + n)->storage) {
824 free ((programs + n)->storage);
825 }
826 if ((programs + n)->stack) {
827 free ((programs + n)->stack);
828 }
829 if ((programs + n)->root) {
830 delelement ((programs + n)->root);
831 }
832 if ((programs + n)->string) {
833 free ((programs + n)->string);
834 (programs + n)->string = NULL;
835 }
836 }
837 }
838
839 /* set program */
840 (programs + n)->id = id;
841 (programs + n)->answer = 0;
842 (programs + n)->storage = NULL;
843 (programs + n)->storage_size = 0;
844 (programs + n)->stack = NULL;
845 (programs + n)->stack_size = 0;
846 (programs + n)->root = dupelement (root);
847 }
848
849 double arg (int id)
850 {
851 double ret = 0;
852 if ((id <= 0) || (id > argument_size)) {
853 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size));
854 } else {
855 ret = argument[id - 1];
856 }
857 return ret;
858 }
859
860 double call (int id, int nbargs, element_t **args)
861 {
862 workspace_t tmp = {0};
863 int i, l, n = -1;
864 double ret = 0;
865
866 if (programs) {
867
868 /* look for program */
869 for (i = 0; i < nb_programs; i++) {
870 if ((programs + i)->id == id) {
871 n = i;
872 break;
873 }
874 }
875 }
876 if (n == -1) {
877 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
878 return 0;
879 }
880
881 /* store context */
882 tmp.answer = answer;
883 tmp.argument = argument;
884 tmp.argument_size = argument_size;
885 tmp.storage = storage;
886 tmp.storage_size = storage_size;
887 tmp.stack = stack;
888 tmp.stack_size = stack_size;
889
890 /* change context */
891 answer = 0;
892 storage = (programs + n)->storage;
893 storage_size = (programs + n)->storage_size;
894 argument = NULL;
895 argument_size = 0;
896 stack = (programs + n)->stack;
897 stack_size = (programs + n)->stack_size;
898 if (nbargs > 0) {
899 argument = (double *) callocordie (nbargs, sizeof (double));
900 for (i = 0, l = 0; i < nbargs; l++) {
901 if (args[l]) {
902 argument[i++] = evaluate_element (args[l], 0);
903 }
904 }
905 argument_size = nbargs;
906 }
907
908 /* evaluate program */
909 element_t *elements = dupelement ((programs + n)->root);
910 ret = evaluate_element (elements, 0);
911 delelement (elements);
912 (programs + n)->answer = answer;
913 (programs + n)->storage = storage;
914 (programs + n)->storage_size = storage_size;
915 if (argument) {
916 free (argument);
917 }
918 (programs + n)->stack = stack;
919 (programs + n)->stack_size = stack_size;
920
921 /* restore context */
922 answer = tmp.answer;
923 storage = tmp.storage;
924 storage_size = tmp.storage_size;
925 argument = tmp.argument;
926 argument_size = tmp.argument_size;
927 stack = tmp.stack;
928 stack_size = tmp.stack_size;
929
930 return ret;
931 }
932
933 void list ()
934 {
935 int i;
936 fprintf (stdout, "programs:");
937 for (i = 0; i < nb_programs; i++) {
938 fprintf (stdout, " %d", (programs + i)->id);
939 }
940 fprintf (stdout, "\n");
941 }
942
943 void edit (int id)
944 {
945 int i, n = -1;
946
947 if (programs) {
948
949 /* look for program */
950 for (i = 0; i < nb_programs; i++) {
951 if ((programs + i)->id == id) {
952 n = i;
953 break;
954 }
955 }
956 }
957 if (n == -1) {
958 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
959 return;
960 }
961
962 /* set string program */
963 fprintf (stdout, "edit: %s\n", (programs + n)->string);
964 }
965
966 void savestring (int id, char *string)
967 {
968 int i, n = -1;
969
970 if (programs) {
971
972 /* look for program */
973 for (i = 0; i < nb_programs; i++) {
974 if ((programs + i)->id == id) {
975 n = i;
976 break;
977 }
978 }
979 }
980
981 /* unnecesary code */
982 //if (n == -1) {
983 // VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
984 // return;
985 //}
986 //if ((programs + n)->string) {
987 // free ((programs + n)->string);
988 //}
989
990 if (string) {
991 (programs + n)->string = strdup (string);
992 }
993 }
994
995 void del (int id)
996 {
997 int i, j, n = -1;
998
999 if (programs) {
1000
1001 /* look for program */
1002 for (i = 0; i < nb_programs; i++) {
1003 if ((programs + i)->id == id) {
1004 n = i;
1005 break;
1006 }
1007 }
1008 }
1009 if (n == -1) {
1010 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
1011 return;
1012 }
1013
1014 /* clean program */
1015 if ((programs + n)->storage) {
1016 free ((programs + n)->storage);
1017 }
1018 if ((programs + n)->stack) {
1019 free ((programs + n)->stack);
1020 }
1021 if ((programs + n)->root) {
1022 delelement ((programs + n)->root);
1023 }
1024 if ((programs + n)->string) {
1025 free ((programs + n)->string);
1026 }
1027
1028 /* remove entry */
1029 workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t));
1030 for (i = 0, j = 0; i < nb_programs; i++) {
1031 if (i != n) {
1032 memcpy (tmp + j, programs + i, sizeof (workspace_t));
1033 j++;
1034 }
1035 }
1036 free (programs);
1037 programs = tmp;
1038 nb_programs--;
1039 }
1040
1041 /* stack management */
1042
1043 double get (int n)
1044 {
1045 double ret = 0;
1046 if ((n <= 0) || (n > stack_size)) {
1047 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size));
1048 } else {
1049 ret = stack[n - 1];
1050 }
1051 return ret;
1052 }
1053
1054 double length ()
1055 {
1056 return stack_size;
1057 }
1058
1059 double pop ()
1060 {
1061 double ret = 0;
1062 if (stack_size > 0) {
1063 ret = stack[--stack_size];
1064 double *tmp = (double *) callocordie (stack_size, sizeof (double));
1065 memcpy (tmp, stack, stack_size * sizeof (double));
1066 free (stack);
1067 stack = tmp;
1068 } else {
1069 VERBOSE (WARNING, fprintf (stdout, "error stack empty\n"));
1070 }
1071 return ret;
1072 }
1073
1074 double push (double val)
1075 {
1076 double *tmp = (double *) callocordie (stack_size + 1, sizeof (double));
1077 memcpy (tmp, stack, stack_size * sizeof (double));
1078 if (stack) {
1079 free (stack);
1080 }
1081 stack = tmp;
1082 stack[stack_size++] = val;
1083 return val;
1084 }
1085
1086 double put (int n, double val)
1087 {
1088 if (n <= 0) {
1089 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size));
1090 return 0;
1091 }
1092 if (n > stack_size) {
1093 double *tmp = (double *) callocordie (n, sizeof (double));
1094 memcpy (tmp, stack, stack_size * sizeof (double));
1095 free (stack);
1096 stack = tmp;
1097 stack_size = n;
1098 }
1099 stack[n - 1] = val;
1100 return val;
1101 }
1102
1103 double set (int nbops, element_t **ops)
1104 {
1105 int i;
1106 if (stack) {
1107 free (stack);
1108 }
1109 stack = NULL;
1110 stack_size = 0;
1111 if (nbops != 0) {
1112 stack = (double *) callocordie (nbops, sizeof (double));
1113 for (i = 0; i < nbops; i++) {
1114 stack[i] = evaluate_element (ops[i], 0);
1115 }
1116 stack_size = nbops;
1117 }
1118 return stack_size;
1119 }
1120
1121 void show (void)
1122 {
1123 int i;
1124 fprintf (stdout, "stack:");
1125 for (i = 0; i < stack_size; i++) {
1126 fprintf (stdout, " ");
1127 fprintf (stdout, minform, stack[i]);
1128 }
1129 fprintf (stdout, "\n");
1130 }
1131
1132 /* stack functions */
1133
1134 double max ()
1135 {
1136 double ret = 0;
1137 int i;
1138 if (stack_size < 1) {
1139 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1140 return 0;
1141 }
1142 ret = stack[0];
1143 for (i = 1; i < stack_size; i++) {
1144 if (stack[i] > ret) {
1145 ret = stack[i];
1146 }
1147 }
1148 return ret;
1149 }
1150
1151 double mean ()
1152 {
1153 double ret = 0;
1154 int i;
1155 if (stack_size < 1) {
1156 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1157 return 0;
1158 }
1159 for (i = 0; i < stack_size; i++) {
1160 ret += stack[i];
1161 }
1162 return ret / stack_size;
1163 }
1164
1165 double min ()
1166 {
1167 double ret = 0;
1168 int i;
1169 if (stack_size < 1) {
1170 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1171 return 0;
1172 }
1173 ret = stack[0];
1174 for (i = 1; i < stack_size; i++) {
1175 if (stack[i] < ret) {
1176 ret = stack[i];
1177 }
1178 }
1179 return ret;
1180 }
1181
1182 void order ()
1183 {
1184 int i, j;
1185 if (stack_size < 1) {
1186 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1187 return;
1188 }
1189 for (i = 0; i < stack_size - 1; i++) {
1190 int done = 0;
1191 for (j = 0; j < stack_size - 1; j++) {
1192 if (stack[j] > stack[j + 1]) {
1193 double tmp = stack[j];
1194 stack[j] = stack[j + 1];
1195 stack[j + 1] = tmp;
1196 done = 1;
1197 }
1198 }
1199 if (done == 0) {
1200 break;
1201 }
1202 }
1203 }
1204
1205 double median ()
1206 {
1207 double ret = 0;
1208 if (stack_size < 3) {
1209 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1210 return 0;
1211 }
1212 double *tmp = (double *) callocordie (stack_size, sizeof (double));
1213 memcpy (tmp, stack, stack_size * sizeof (double));
1214 order ();
1215 ret = stack[(stack_size - 1)/ 2];
1216 memcpy (stack, tmp, stack_size * sizeof (double));
1217 free (tmp);
1218 return ret;
1219 }
1220
1221 double prod ()
1222 {
1223 double ret = 1;
1224 int i;
1225 if (stack_size < 1) {
1226 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1227 return 0;
1228 }
1229 for (i = 0; i < stack_size; i++) {
1230 ret *= stack[i];
1231 }
1232 return ret;
1233 }
1234
1235 double sum ()
1236 {
1237 double ret = 0;
1238 int i;
1239 if (stack_size < 1) {
1240 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1241 return 0;
1242 }
1243 for (i = 0; i < stack_size; i++) {
1244 ret += stack[i];
1245 }
1246 return ret;
1247 }
1248
1249 double variance ()
1250 {
1251 double ret = 0;
1252 double m = 0;
1253 int i;
1254 if (stack_size < 2) {
1255 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1256 return 0;
1257 }
1258 m = mean ();
1259 for (i = 0; i < stack_size; i++) {
1260 ret += (stack[i] - m) * (stack[i] - m);
1261 }
1262 return ret / stack_size;
1263 }
1264
1265
1266 /* help message */
1267
1268 void help (void)
1269 {
1270 fprintf (stdout, "calc is a simple calculator\n\n");
1271 fprintf (stdout, "arithmetic op.:");
1272 fprintf (stdout, " + - * / %% ^\n");
1273 fprintf (stdout, "comparison op.:");
1274 fprintf (stdout, " == != >= <= > <\n");
1275 fprintf (stdout, "logical op.:");
1276 fprintf (stdout, " & | !\n");
1277 fprintf (stdout, "mathematic func.:");
1278 fprintf (stdout, " exp ln log pow sqrt\n");
1279 fprintf (stdout, "trigonometric func.:");
1280 fprintf (stdout, " acos asin atan cos sin tan\n");
1281 fprintf (stdout, "error functions:");
1282 fprintf (stdout, " erf erfc\n");
1283 fprintf (stdout, "miscellaneous func.:");
1284 fprintf (stdout, " abs ceil floor\n");
1285 fprintf (stdout, "storage func.:");
1286 fprintf (stdout, " clear dec disp inc mem rcl sto\n");
1287 fprintf (stdout, "control flow prim.:");
1288 fprintf (stdout, " cond print while {} ;\n");
1289 fprintf (stdout, "program management:");
1290 fprintf (stdout, " arg call del edit ls prog\n");
1291 fprintf (stdout, "stack management:");
1292 fprintf (stdout, " get len pop push put set show\n");
1293 fprintf (stdout, "stack func.:");
1294 fprintf (stdout, " max mean med min ord prod sum var\n");
1295 fprintf (stdout, "control management:");
1296 fprintf (stdout, " help quit\n");
1297 fprintf (stdout, "constants:");
1298 fprintf (stdout, " ans e pi\n");
1299 }
1300
1301 /* evaluate element tree */
1302
1303 #define MASK_SUB 0x1
1304 #define MASK_DIV 0x2
1305
1306 double evaluate_element (element_t *root, char mask)
1307 {
1308 double op0 = 0, op1 = 0;
1309 char nextmask = mask;
1310 int i, nb;
1311
1312 if ((root == NULL) || (root == ERROR_OP)) {
1313 VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n"));
1314 return 0;
1315 }
1316
1317 /* mask to manage sub operator sub and div */
1318 switch (root->func) {
1319 case Add:
1320 nextmask &= ~MASK_SUB;
1321 nextmask &= ~MASK_DIV;
1322 break;
1323 case Sub:
1324 nextmask |= MASK_SUB;
1325 nextmask &= ~MASK_DIV;
1326 break;
1327 case Mul:
1328 nextmask &= ~MASK_DIV;
1329 break;
1330 case Div:
1331 nextmask |= MASK_DIV;
1332 break;
1333 default:
1334 nextmask = mask;
1335 }
1336
1337 switch (root->func) {
1338 case Val:
1339 case Sig:
1340 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
1341 break;
1342 case Add:
1343 case Sub:
1344 case Mul:
1345 case Div:
1346 case Mod:
1347 case Pow:
1348 case Store:
1349 case Equal:
1350 case Diff:
1351 case Ge:
1352 case Le:
1353 case Gt:
1354 case Lt:
1355 case And:
1356 case Or:
1357 if (root->ops[1]) {
1358 op1 = evaluate_element (root->ops[1], nextmask);
1359 } else if (root->func != Store) {
1360 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
1361 return 0;
1362 }
1363 /* fallthrough */
1364 case Sqr:
1365 case Cos:
1366 case Sin:
1367 case Tan:
1368 case Acos:
1369 case Asin:
1370 case Atan:
1371 case Ln:
1372 case Log:
1373 case Exp:
1374 case Erfc:
1375 case Erf:
1376 case Abs:
1377 case Ceil:
1378 case Floor:
1379 case Recall:
1380 case Inc:
1381 case Dec:
1382 case Not:
1383 case Mem:
1384 case Cond:
1385 case Prog:
1386 case Arg:
1387 case Call:
1388 case Edit:
1389 case Del:
1390 case Get:
1391 if (root->ops[0]) {
1392 op0 = evaluate_element (root->ops[0], 0);
1393 } else {
1394 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1395 return 0;
1396 }
1397 break;
1398 case Disp:
1399 case Clear:
1400 case Quit:
1401 case Help:
1402 case Ans:
1403 case Pi:
1404 case E:
1405 case Code:
1406 case List:
1407 case Length:
1408 case Pop:
1409 case Set:
1410 case Show:
1411 case Median:
1412 case Order:
1413 case Prod:
1414 case Sum:
1415 break;
1416 case While:
1417 if (root->ops[0] == NULL) {
1418 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1419 return 0;
1420 }
1421 break;
1422 case Push:
1423 case Print:
1424 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
1425 break;
1426 case Put:
1427 if (root->ops[0]) {
1428 op0 = evaluate_element (root->ops[0], 0);
1429 } else {
1430 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1431 return 0;
1432 }
1433 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
1434 break;
1435 case Max:
1436 case Mean:
1437 case Min:
1438 case Variance:
1439 if (root->ops[0]) {
1440 op0 = evaluate_element (root->ops[0], 0);
1441 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
1442 }
1443 }
1444
1445 switch (root->func) {
1446 case Val: return op0;
1447 case Sig: return -op0;
1448 case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1;
1449 case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1;
1450 case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1;
1451 case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1;
1452 case Mod: return fmod (op0, op1);
1453 case Pow: return pow (op0, op1);
1454 case Sqr: return sqrt (op0);
1455 case Cos: return cos (op0);
1456 case Sin: return sin (op0);
1457 case Tan: return tan (op0);
1458 case Acos: return acos (op0);
1459 case Asin: return asin (op0);
1460 case Atan: return atan (op0);
1461 case Ln: return log (op0);
1462 case Log: return log10 (op0);
1463 case Exp: return exp (op0);
1464 case Erfc: return erfc (op0);
1465 case Erf: return erf (op0);
1466 case Abs: return fabs (op0);
1467 case Ceil: return ceil (op0);
1468 case Floor: return floor (op0);
1469 case Store: return store ((int)op0, (op1) ? op1 : answer);
1470 case Recall: return recall ((int)op0);
1471 case Inc: return increase ((int)op0);
1472 case Dec: return decrease ((int)op0);
1473 case Disp: display (); break;
1474 case Mem: memory ((int)op0); break;
1475 case Clear: clear (); break;
1476 case Quit: quit (); break;
1477 case Help: help (); break;
1478 case Ans: return answer;
1479 case Pi: return M_PI;
1480 case E: return M_E;
1481 case Equal: return op0 == op1;
1482 case Diff: return op0 != op1;
1483 case Ge: return op0 >= op1;
1484 case Le: return op0 <= op1;
1485 case Gt: return op0 > op1;
1486 case Lt: return op0 < op1;
1487 case And: return (op0 != 0) && (op1 != 0);
1488 case Or: return (op0 != 0) || (op1 != 0);
1489 case Not: return (op0 == 0);
1490 case Cond:
1491 if ((op0) && (root->ops[1])) {
1492 return evaluate_element (root->ops[1], 0);
1493 } else if ((!op0) && (root->ops[2])) {
1494 return evaluate_element (root->ops[2], 0);
1495 } else {
1496 return 0;
1497 }
1498 case While: return while_do (root->ops[0], root->ops[1]);
1499 case Code: return execute_code (root->ops, root->nbops);
1500 case Print: return print (op0);
1501 case Prog:
1502 prog ((int)op0, root->ops[1]);
1503 savestring ((int)op0, root->string);
1504 break;
1505 case Arg: return arg ((int)op0);
1506 case Call:
1507 for (i = 1, nb =0; i < root->nbops; i++) {
1508 if (root->ops[i]) {
1509 nb++;
1510 }
1511 }
1512 return call ((int)op0, nb, root->ops + 1);
1513 case List: list (); break;
1514 case Edit: edit ((int)op0); break;
1515 case Del: del ((int)op0); break;
1516 case Get: return get ((int)op0);
1517 case Length: return length ();
1518 case Pop: return pop ();
1519 case Push: return push (op0);
1520 case Put: return put ((int)op0, op1);
1521 case Set:
1522 for (i = 0, nb =0; i < root->nbops; i++) {
1523 if (root->ops[i]) {
1524 nb++;
1525 }
1526 }
1527 return set (nb, root->ops);
1528 case Show: show (); break;
1529 case Max:
1530 if (root->ops[0]) {
1531 return op0 > op1 ? op0 : op1;
1532 }
1533 return max ();
1534 case Mean:
1535 if (root->ops[0]) {
1536 return (op0 + op1) / 2;
1537 }
1538 return mean ();
1539 case Median: return median ();
1540 case Min:
1541 if (root->ops[0]) {
1542 return op0 < op1 ? op0 : op1;
1543 }
1544 return min ();
1545 case Order: order (); break;
1546 case Prod: return prod ();
1547 case Sum: return sum ();
1548 case Variance:
1549 if (root->ops[0]) {
1550 double m = (op0 + op1) / 2;
1551 op0 -= m;
1552 op1 -= m;
1553 return op0 * op0 + op1 * op1;
1554 }
1555 return variance ();
1556 }
1557
1558 return 0;
1559 }
1560
1561 char **generate_completion_list ()
1562 {
1563 int i, j, l = 0;
1564 char **list = (char **) callocordie (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *));
1565
1566 for (i = 0; i < NB_OPERATORS; i++) {
1567 list[l] = strdup ((operators + i)->keyword);
1568 for (j = 0; j < (int)strlen (list[l]); j++) {
1569 if (list[i][j] == '\t') {
1570 list[i][j] = '\0';
1571 }
1572 }
1573 if (list[l] != NULL) {
1574 l++;
1575 }
1576 }
1577
1578 for (i = 0; i < NB_FUNCTIONS; i++) {
1579 list[l] = strdup ((functions + i)->keyword);
1580 if (list[l] != NULL) {
1581 l++;
1582 }
1583 }
1584
1585 for (i = 0; i < NB_CONSTANTS; i++) {
1586 list[l] = strdup ((constants + i)->keyword);
1587 if (list[l] != NULL) {
1588 l++;
1589 }
1590 }
1591
1592 for (i = 0; i < NB_SYMBOLS; i++) {
1593 list[l] = strdup (symbols[i]);
1594 if (list[l] != NULL) {
1595 l++;
1596 }
1597 }
1598
1599 return (list);
1600 }
1601
1602 void free_completion_list (char **list)
1603 {
1604 int i;
1605
1606 if (list) {
1607 for (i = 0; i < NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1; i++) {
1608 if (list[i] != NULL) {
1609 free (list[i]);
1610 }
1611 }
1612 free (list);
1613 }
1614 }
1615
1616
1617 /* vim: set ts=4 sw=4 et: */