mem without argument returns size
[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", Memory, 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 Memory: 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 int memory (int nb)
619 {
620 int i, l;
621 double *tmp = NULL;
622 if ((nb != -1) && (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 if (storage_size == -1) {
635 memory (DEFAULT_STORAGE_SIZE);
636 }
637 return storage_size;
638 }
639
640 double store (int index, double value)
641 {
642 if (storage_size == -1) {
643 memory (DEFAULT_STORAGE_SIZE);
644 }
645 if ((index > 0) && (index <= storage_size)) {
646 storage[index - 1] = value;
647 } else {
648 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
649 }
650 return value;
651 }
652
653 double recall (int index)
654 {
655 if (storage_size == -1) {
656 memory (DEFAULT_STORAGE_SIZE);
657 }
658 if ((index > 0) && (index <= storage_size)) {
659 return storage[index - 1];
660 } else {
661 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
662 }
663 return 0;
664 }
665
666 double increase (int index)
667 {
668 if (storage_size == -1) {
669 memory (DEFAULT_STORAGE_SIZE);
670 }
671 if ((index > 0) && (index <= storage_size)) {
672 return storage[index - 1]++;
673 } else {
674 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
675 }
676 return 0;
677 }
678
679 double decrease (int index)
680 {
681 if (storage_size == -1) {
682 memory (DEFAULT_STORAGE_SIZE);
683 }
684 if ((index > 0) && (index <= storage_size)) {
685 return storage[index - 1]--;
686 } else {
687 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
688 }
689 return 0;
690 }
691
692 void display (void)
693 {
694 int i;
695 if (storage_size == -1) {
696 memory (DEFAULT_STORAGE_SIZE);
697 }
698 fprintf (stdout, "storage:");
699 for (i = 0; i < storage_size; i++) {
700 fprintf (stdout, " ");
701 fprintf (stdout, minform, storage[i]);
702 }
703 fprintf (stdout, "\n");
704 }
705
706 void clear ()
707 {
708 int i;
709 for (i = 0; i < storage_size; i++) {
710 storage[i] = 0;
711 }
712 }
713
714 /* While do function */
715
716 double while_do (element_t *cond, element_t *action)
717 {
718 double ret = 0;
719 element_t *temp = NULL;
720
721 VERBOSE (DEBUG, fprintf (stdout, "starting while loop\n"));
722 while (1) {
723 VERBOSE (DEBUG, fprintf (stdout, "loop...\n"));
724
725 temp = dupelement (cond);
726 double test = evaluate_element (temp, 0);
727 delelement (temp);
728 if (!test) {
729 break;
730 }
731 if (action) {
732 temp = dupelement (action);
733 ret = evaluate_element (temp, 0);
734 delelement (temp);
735 }
736 }
737
738 VERBOSE (DEBUG, fprintf (stdout, "ending while loop\n"));
739
740 return ret;
741 }
742
743 /* program function */
744
745 double execute_code (element_t **prog, int nbcalls)
746 {
747 double ret = 0;
748 int i;
749 for (i = 0; i < nbcalls; i++) {
750 ret = evaluate_element (prog[i], 0);
751 }
752 return ret;
753 }
754
755 /* print function */
756
757 void set_format (char *prompt, int precision)
758 {
759 char buffer[128] = {0};
760 free_format ();
761 sprintf (buffer, "%s%%.%dg\n", prompt, precision);
762 format = strdup (buffer);
763 sprintf (buffer, "%%.%dg", precision);
764 minform = strdup (buffer);
765 }
766
767 void free_format ()
768 {
769 if (format) {
770 free (format);
771 format = NULL;
772 }
773 if (minform) {
774 free (minform);
775 minform = NULL;
776 }
777 }
778
779 double print (double value)
780 {
781 fprintf (stdout, format ? format : DEFAULT_FORMAT, value);
782 fflush (stdout);
783 return value;
784 }
785
786 /* quit function */
787
788 void quit (void)
789 {
790 fprintf (stdout, "bye\n");
791 exit (0);
792 }
793
794 /* program function */
795
796 void prog (int id, element_t *root)
797 {
798 int i, n = -1;
799
800 if (programs == NULL) {
801
802 /* initial memory allocation */
803 programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
804 nb_programs = 1;
805 n = 0;
806
807 } else {
808
809 /* look for existing program */
810 for (i = 0; i < nb_programs; i++) {
811 if ((programs + i)->id == id) {
812 n = i;
813 break;
814 }
815 }
816 if (n == -1) {
817
818 /* new program */
819 n = nb_programs++;
820 workspace_t *tmp = (workspace_t *) callocordie (nb_programs, sizeof (workspace_t));
821 memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t));
822 free (programs);
823 programs = tmp;
824 } else {
825
826 /* clean old program */
827 if ((programs + n)->storage) {
828 free ((programs + n)->storage);
829 }
830 if ((programs + n)->stack) {
831 free ((programs + n)->stack);
832 }
833 if ((programs + n)->root) {
834 delelement ((programs + n)->root);
835 }
836 if ((programs + n)->string) {
837 free ((programs + n)->string);
838 (programs + n)->string = NULL;
839 }
840 }
841 }
842
843 /* set program */
844 (programs + n)->id = id;
845 (programs + n)->answer = 0;
846 (programs + n)->storage = NULL;
847 (programs + n)->storage_size = 0;
848 (programs + n)->stack = NULL;
849 (programs + n)->stack_size = 0;
850 (programs + n)->root = dupelement (root);
851 }
852
853 double arg (int id)
854 {
855 double ret = 0;
856 if ((id <= 0) || (id > argument_size)) {
857 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size));
858 } else {
859 ret = argument[id - 1];
860 }
861 return ret;
862 }
863
864 double call (int id, int nbargs, element_t **args)
865 {
866 workspace_t tmp = {0};
867 int i, l, n = -1;
868 double ret = 0;
869
870 if (programs) {
871
872 /* look for program */
873 for (i = 0; i < nb_programs; i++) {
874 if ((programs + i)->id == id) {
875 n = i;
876 break;
877 }
878 }
879 }
880 if (n == -1) {
881 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
882 return 0;
883 }
884
885 /* store context */
886 tmp.answer = answer;
887 tmp.argument = argument;
888 tmp.argument_size = argument_size;
889 tmp.storage = storage;
890 tmp.storage_size = storage_size;
891 tmp.stack = stack;
892 tmp.stack_size = stack_size;
893
894 /* change context */
895 answer = 0;
896 storage = (programs + n)->storage;
897 storage_size = (programs + n)->storage_size;
898 argument = NULL;
899 argument_size = 0;
900 stack = (programs + n)->stack;
901 stack_size = (programs + n)->stack_size;
902 if (nbargs > 0) {
903 argument = (double *) callocordie (nbargs, sizeof (double));
904 for (i = 0, l = 0; i < nbargs; l++) {
905 if (args[l]) {
906 argument[i++] = evaluate_element (args[l], 0);
907 }
908 }
909 argument_size = nbargs;
910 }
911
912 /* evaluate program */
913 element_t *elements = dupelement ((programs + n)->root);
914 ret = evaluate_element (elements, 0);
915 delelement (elements);
916 (programs + n)->answer = answer;
917 (programs + n)->storage = storage;
918 (programs + n)->storage_size = storage_size;
919 if (argument) {
920 free (argument);
921 }
922 (programs + n)->stack = stack;
923 (programs + n)->stack_size = stack_size;
924
925 /* restore context */
926 answer = tmp.answer;
927 storage = tmp.storage;
928 storage_size = tmp.storage_size;
929 argument = tmp.argument;
930 argument_size = tmp.argument_size;
931 stack = tmp.stack;
932 stack_size = tmp.stack_size;
933
934 return ret;
935 }
936
937 void list ()
938 {
939 int i;
940 fprintf (stdout, "programs:");
941 for (i = 0; i < nb_programs; i++) {
942 fprintf (stdout, " %d", (programs + i)->id);
943 }
944 fprintf (stdout, "\n");
945 }
946
947 void edit (int id)
948 {
949 int i, n = -1;
950
951 if (programs) {
952
953 /* look for program */
954 for (i = 0; i < nb_programs; i++) {
955 if ((programs + i)->id == id) {
956 n = i;
957 break;
958 }
959 }
960 }
961 if (n == -1) {
962 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
963 return;
964 }
965
966 /* set string program */
967 fprintf (stdout, "edit: %s\n", (programs + n)->string);
968 }
969
970 void savestring (int id, char *string)
971 {
972 int i, n = -1;
973
974 if (programs) {
975
976 /* look for program */
977 for (i = 0; i < nb_programs; i++) {
978 if ((programs + i)->id == id) {
979 n = i;
980 break;
981 }
982 }
983 }
984
985 /* unnecesary code */
986 //if (n == -1) {
987 // VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
988 // return;
989 //}
990 //if ((programs + n)->string) {
991 // free ((programs + n)->string);
992 //}
993
994 if (string) {
995 (programs + n)->string = strdup (string);
996 }
997 }
998
999 void del (int id)
1000 {
1001 int i, j, n = -1;
1002
1003 if (programs) {
1004
1005 /* look for program */
1006 for (i = 0; i < nb_programs; i++) {
1007 if ((programs + i)->id == id) {
1008 n = i;
1009 break;
1010 }
1011 }
1012 }
1013 if (n == -1) {
1014 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
1015 return;
1016 }
1017
1018 /* clean program */
1019 if ((programs + n)->storage) {
1020 free ((programs + n)->storage);
1021 }
1022 if ((programs + n)->stack) {
1023 free ((programs + n)->stack);
1024 }
1025 if ((programs + n)->root) {
1026 delelement ((programs + n)->root);
1027 }
1028 if ((programs + n)->string) {
1029 free ((programs + n)->string);
1030 }
1031
1032 /* remove entry */
1033 workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t));
1034 for (i = 0, j = 0; i < nb_programs; i++) {
1035 if (i != n) {
1036 memcpy (tmp + j, programs + i, sizeof (workspace_t));
1037 j++;
1038 }
1039 }
1040 free (programs);
1041 programs = tmp;
1042 nb_programs--;
1043 }
1044
1045 /* stack management */
1046
1047 double get (int n)
1048 {
1049 double ret = 0;
1050 if ((n <= 0) || (n > stack_size)) {
1051 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size));
1052 } else {
1053 ret = stack[n - 1];
1054 }
1055 return ret;
1056 }
1057
1058 double length ()
1059 {
1060 return stack_size;
1061 }
1062
1063 double pop ()
1064 {
1065 double ret = 0;
1066 if (stack_size > 0) {
1067 ret = stack[--stack_size];
1068 double *tmp = (double *) callocordie (stack_size, sizeof (double));
1069 memcpy (tmp, stack, stack_size * sizeof (double));
1070 free (stack);
1071 stack = tmp;
1072 } else {
1073 VERBOSE (WARNING, fprintf (stdout, "error stack empty\n"));
1074 }
1075 return ret;
1076 }
1077
1078 double push (double val)
1079 {
1080 double *tmp = (double *) callocordie (stack_size + 1, sizeof (double));
1081 memcpy (tmp, stack, stack_size * sizeof (double));
1082 if (stack) {
1083 free (stack);
1084 }
1085 stack = tmp;
1086 stack[stack_size++] = val;
1087 return val;
1088 }
1089
1090 double put (int n, double val)
1091 {
1092 if (n <= 0) {
1093 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size));
1094 return 0;
1095 }
1096 if (n > stack_size) {
1097 double *tmp = (double *) callocordie (n, sizeof (double));
1098 memcpy (tmp, stack, stack_size * sizeof (double));
1099 free (stack);
1100 stack = tmp;
1101 stack_size = n;
1102 }
1103 stack[n - 1] = val;
1104 return val;
1105 }
1106
1107 double set (int nbops, element_t **ops)
1108 {
1109 int i;
1110 if (stack) {
1111 free (stack);
1112 }
1113 stack = NULL;
1114 stack_size = 0;
1115 if (nbops != 0) {
1116 stack = (double *) callocordie (nbops, sizeof (double));
1117 for (i = 0; i < nbops; i++) {
1118 stack[i] = evaluate_element (ops[i], 0);
1119 }
1120 stack_size = nbops;
1121 }
1122 return stack_size;
1123 }
1124
1125 void show (void)
1126 {
1127 int i;
1128 fprintf (stdout, "stack:");
1129 for (i = 0; i < stack_size; i++) {
1130 fprintf (stdout, " ");
1131 fprintf (stdout, minform, stack[i]);
1132 }
1133 fprintf (stdout, "\n");
1134 }
1135
1136 /* stack functions */
1137
1138 double max ()
1139 {
1140 double ret = 0;
1141 int i;
1142 if (stack_size < 1) {
1143 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1144 return 0;
1145 }
1146 ret = stack[0];
1147 for (i = 1; i < stack_size; i++) {
1148 if (stack[i] > ret) {
1149 ret = stack[i];
1150 }
1151 }
1152 return ret;
1153 }
1154
1155 double mean ()
1156 {
1157 double ret = 0;
1158 int i;
1159 if (stack_size < 1) {
1160 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1161 return 0;
1162 }
1163 for (i = 0; i < stack_size; i++) {
1164 ret += stack[i];
1165 }
1166 return ret / stack_size;
1167 }
1168
1169 double min ()
1170 {
1171 double ret = 0;
1172 int i;
1173 if (stack_size < 1) {
1174 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1175 return 0;
1176 }
1177 ret = stack[0];
1178 for (i = 1; i < stack_size; i++) {
1179 if (stack[i] < ret) {
1180 ret = stack[i];
1181 }
1182 }
1183 return ret;
1184 }
1185
1186 void order ()
1187 {
1188 int i, j;
1189 if (stack_size < 1) {
1190 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1191 return;
1192 }
1193 for (i = 0; i < stack_size - 1; i++) {
1194 int done = 0;
1195 for (j = 0; j < stack_size - 1; j++) {
1196 if (stack[j] > stack[j + 1]) {
1197 double tmp = stack[j];
1198 stack[j] = stack[j + 1];
1199 stack[j + 1] = tmp;
1200 done = 1;
1201 }
1202 }
1203 if (done == 0) {
1204 break;
1205 }
1206 }
1207 }
1208
1209 double median ()
1210 {
1211 double ret = 0;
1212 if (stack_size < 3) {
1213 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1214 return 0;
1215 }
1216 double *tmp = (double *) callocordie (stack_size, sizeof (double));
1217 memcpy (tmp, stack, stack_size * sizeof (double));
1218 order ();
1219 ret = stack[(stack_size - 1)/ 2];
1220 memcpy (stack, tmp, stack_size * sizeof (double));
1221 free (tmp);
1222 return ret;
1223 }
1224
1225 double prod ()
1226 {
1227 double ret = 1;
1228 int i;
1229 if (stack_size < 1) {
1230 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1231 return 0;
1232 }
1233 for (i = 0; i < stack_size; i++) {
1234 ret *= stack[i];
1235 }
1236 return ret;
1237 }
1238
1239 double sum ()
1240 {
1241 double ret = 0;
1242 int i;
1243 if (stack_size < 1) {
1244 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1245 return 0;
1246 }
1247 for (i = 0; i < stack_size; i++) {
1248 ret += stack[i];
1249 }
1250 return ret;
1251 }
1252
1253 double variance ()
1254 {
1255 double ret = 0;
1256 double m = 0;
1257 int i;
1258 if (stack_size < 2) {
1259 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1260 return 0;
1261 }
1262 m = mean ();
1263 for (i = 0; i < stack_size; i++) {
1264 ret += (stack[i] - m) * (stack[i] - m);
1265 }
1266 return ret / stack_size;
1267 }
1268
1269
1270 /* help message */
1271
1272 void help (void)
1273 {
1274 fprintf (stdout, "calc is a simple calculator\n\n");
1275 fprintf (stdout, "arithmetic op.:");
1276 fprintf (stdout, " + - * / %% ^\n");
1277 fprintf (stdout, "comparison op.:");
1278 fprintf (stdout, " == != >= <= > <\n");
1279 fprintf (stdout, "logical op.:");
1280 fprintf (stdout, " & | !\n");
1281 fprintf (stdout, "mathematic func.:");
1282 fprintf (stdout, " exp ln log pow sqrt\n");
1283 fprintf (stdout, "trigonometric func.:");
1284 fprintf (stdout, " acos asin atan cos sin tan\n");
1285 fprintf (stdout, "error functions:");
1286 fprintf (stdout, " erf erfc\n");
1287 fprintf (stdout, "miscellaneous func.:");
1288 fprintf (stdout, " abs ceil floor\n");
1289 fprintf (stdout, "storage func.:");
1290 fprintf (stdout, " clear dec disp inc mem rcl sto\n");
1291 fprintf (stdout, "control flow prim.:");
1292 fprintf (stdout, " cond print while {} ;\n");
1293 fprintf (stdout, "program management:");
1294 fprintf (stdout, " arg call del edit ls prog\n");
1295 fprintf (stdout, "stack management:");
1296 fprintf (stdout, " get len pop push put set show\n");
1297 fprintf (stdout, "stack func.:");
1298 fprintf (stdout, " max mean med min ord prod sum var\n");
1299 fprintf (stdout, "control management:");
1300 fprintf (stdout, " help quit\n");
1301 fprintf (stdout, "constants:");
1302 fprintf (stdout, " ans e pi\n");
1303 }
1304
1305 /* evaluate element tree */
1306
1307 #define MASK_SUB 0x1
1308 #define MASK_DIV 0x2
1309
1310 double evaluate_element (element_t *root, char mask)
1311 {
1312 double op0 = 0, op1 = 0;
1313 char nextmask = mask;
1314 int i, nb;
1315
1316 if ((root == NULL) || (root == ERROR_OP)) {
1317 VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n"));
1318 return 0;
1319 }
1320
1321 /* mask to manage sub operator sub and div */
1322 switch (root->func) {
1323 case Add:
1324 nextmask &= ~MASK_SUB;
1325 nextmask &= ~MASK_DIV;
1326 break;
1327 case Sub:
1328 nextmask |= MASK_SUB;
1329 nextmask &= ~MASK_DIV;
1330 break;
1331 case Mul:
1332 nextmask &= ~MASK_DIV;
1333 break;
1334 case Div:
1335 nextmask |= MASK_DIV;
1336 break;
1337 default:
1338 nextmask = mask;
1339 }
1340
1341 switch (root->func) {
1342 case Val:
1343 case Sig:
1344 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
1345 break;
1346 case Add:
1347 case Sub:
1348 case Mul:
1349 case Div:
1350 case Mod:
1351 case Pow:
1352 case Equal:
1353 case Diff:
1354 case Ge:
1355 case Le:
1356 case Gt:
1357 case Lt:
1358 case And:
1359 case Or:
1360 if (root->ops[1]) {
1361 op1 = evaluate_element (root->ops[1], nextmask);
1362 } else {
1363 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
1364 return 0;
1365 }
1366 /* fallthrough */
1367 case Sqr:
1368 case Cos:
1369 case Sin:
1370 case Tan:
1371 case Acos:
1372 case Asin:
1373 case Atan:
1374 case Ln:
1375 case Log:
1376 case Exp:
1377 case Erfc:
1378 case Erf:
1379 case Abs:
1380 case Ceil:
1381 case Floor:
1382 case Recall:
1383 case Inc:
1384 case Dec:
1385 case Not:
1386 case Cond:
1387 case Prog:
1388 case Arg:
1389 case Call:
1390 case Edit:
1391 case Del:
1392 case Get:
1393 if (root->ops[0]) {
1394 op0 = evaluate_element (root->ops[0], 0);
1395 } else {
1396 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1397 return 0;
1398 }
1399 break;
1400 case Disp:
1401 case Clear:
1402 case Quit:
1403 case Help:
1404 case Ans:
1405 case Pi:
1406 case E:
1407 case Code:
1408 case List:
1409 case Length:
1410 case Pop:
1411 case Set:
1412 case Show:
1413 case Median:
1414 case Order:
1415 case Prod:
1416 case Sum:
1417 break;
1418 case While:
1419 if (root->ops[0] == NULL) {
1420 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1421 return 0;
1422 }
1423 break;
1424 case Memory:
1425 if (root->ops[0] == NULL) {
1426 op0 = -1;
1427 } else {
1428 op0 = (int)evaluate_element (root->ops[0], 0);
1429 if (op0 < 0) {
1430 VERBOSE (WARNING, fprintf (stdout, "error incorrect memory size (%d)\n", (int)op0));
1431 return 0;
1432 }
1433 }
1434 break;
1435 case Push:
1436 case Print:
1437 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
1438 break;
1439 case Store:
1440 case Put:
1441 if (root->ops[0]) {
1442 op0 = evaluate_element (root->ops[0], 0);
1443 } else {
1444 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1445 return 0;
1446 }
1447 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
1448 break;
1449 case Max:
1450 case Mean:
1451 case Min:
1452 case Variance:
1453 if (root->ops[0]) {
1454 op0 = evaluate_element (root->ops[0], 0);
1455 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
1456 }
1457 }
1458
1459 switch (root->func) {
1460 case Val: return op0;
1461 case Sig: return -op0;
1462 case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1;
1463 case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1;
1464 case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1;
1465 case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1;
1466 case Mod: return fmod (op0, op1);
1467 case Pow: return pow (op0, op1);
1468 case Sqr: return sqrt (op0);
1469 case Cos: return cos (op0);
1470 case Sin: return sin (op0);
1471 case Tan: return tan (op0);
1472 case Acos: return acos (op0);
1473 case Asin: return asin (op0);
1474 case Atan: return atan (op0);
1475 case Ln: return log (op0);
1476 case Log: return log10 (op0);
1477 case Exp: return exp (op0);
1478 case Erfc: return erfc (op0);
1479 case Erf: return erf (op0);
1480 case Abs: return fabs (op0);
1481 case Ceil: return ceil (op0);
1482 case Floor: return floor (op0);
1483 case Store: return store ((int)op0, op1);
1484 case Recall: return recall ((int)op0);
1485 case Inc: return increase ((int)op0);
1486 case Dec: return decrease ((int)op0);
1487 case Disp: display (); break;
1488 case Memory: return memory ((root->ops[0]) ? (int)op0 : -1);
1489 case Clear: clear (); break;
1490 case Quit: quit (); break;
1491 case Help: help (); break;
1492 case Ans: return answer;
1493 case Pi: return M_PI;
1494 case E: return M_E;
1495 case Equal: return op0 == op1;
1496 case Diff: return op0 != op1;
1497 case Ge: return op0 >= op1;
1498 case Le: return op0 <= op1;
1499 case Gt: return op0 > op1;
1500 case Lt: return op0 < op1;
1501 case And: return (op0 != 0) && (op1 != 0);
1502 case Or: return (op0 != 0) || (op1 != 0);
1503 case Not: return (op0 == 0);
1504 case Cond:
1505 if ((op0) && (root->ops[1])) {
1506 return evaluate_element (root->ops[1], 0);
1507 } else if ((!op0) && (root->ops[2])) {
1508 return evaluate_element (root->ops[2], 0);
1509 } else {
1510 return 0;
1511 }
1512 case While: return while_do (root->ops[0], root->ops[1]);
1513 case Code: return execute_code (root->ops, root->nbops);
1514 case Print: return print (op0);
1515 case Prog:
1516 prog ((int)op0, root->ops[1]);
1517 savestring ((int)op0, root->string);
1518 break;
1519 case Arg: return arg ((int)op0);
1520 case Call:
1521 for (i = 1, nb =0; i < root->nbops; i++) {
1522 if (root->ops[i]) {
1523 nb++;
1524 }
1525 }
1526 return call ((int)op0, nb, root->ops + 1);
1527 case List: list (); break;
1528 case Edit: edit ((int)op0); break;
1529 case Del: del ((int)op0); break;
1530 case Get: return get ((int)op0);
1531 case Length: return length ();
1532 case Pop: return pop ();
1533 case Push: return push (op0);
1534 case Put: return put ((int)op0, op1);
1535 case Set:
1536 for (i = 0, nb =0; i < root->nbops; i++) {
1537 if (root->ops[i]) {
1538 nb++;
1539 }
1540 }
1541 return set (nb, root->ops);
1542 case Show: show (); break;
1543 case Max:
1544 if (root->ops[0]) {
1545 return op0 > op1 ? op0 : op1;
1546 }
1547 return max ();
1548 case Mean:
1549 if (root->ops[0]) {
1550 return (op0 + op1) / 2;
1551 }
1552 return mean ();
1553 case Median: return median ();
1554 case Min:
1555 if (root->ops[0]) {
1556 return op0 < op1 ? op0 : op1;
1557 }
1558 return min ();
1559 case Order: order (); break;
1560 case Prod: return prod ();
1561 case Sum: return sum ();
1562 case Variance:
1563 if (root->ops[0]) {
1564 double m = (op0 + op1) / 2;
1565 op0 -= m;
1566 op1 -= m;
1567 return op0 * op0 + op1 * op1;
1568 }
1569 return variance ();
1570 }
1571
1572 return 0;
1573 }
1574
1575 char **generate_completion_list ()
1576 {
1577 int i, j, l = 0;
1578 char **list = (char **) callocordie (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *));
1579
1580 for (i = 0; i < NB_OPERATORS; i++) {
1581 list[l] = strdup ((operators + i)->keyword);
1582 for (j = 0; j < (int)strlen (list[l]); j++) {
1583 if (list[i][j] == '\t') {
1584 list[i][j] = '\0';
1585 }
1586 }
1587 if (list[l] != NULL) {
1588 l++;
1589 }
1590 }
1591
1592 for (i = 0; i < NB_FUNCTIONS; i++) {
1593 list[l] = strdup ((functions + i)->keyword);
1594 if (list[l] != NULL) {
1595 l++;
1596 }
1597 }
1598
1599 for (i = 0; i < NB_CONSTANTS; i++) {
1600 list[l] = strdup ((constants + i)->keyword);
1601 if (list[l] != NULL) {
1602 l++;
1603 }
1604 }
1605
1606 for (i = 0; i < NB_SYMBOLS; i++) {
1607 list[l] = strdup (symbols[i]);
1608 if (list[l] != NULL) {
1609 l++;
1610 }
1611 }
1612
1613 return (list);
1614 }
1615
1616 void free_completion_list (char **list)
1617 {
1618 int i;
1619
1620 if (list) {
1621 for (i = 0; i < NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1; i++) {
1622 if (list[i] != NULL) {
1623 free (list[i]);
1624 }
1625 }
1626 free (list);
1627 }
1628 }
1629
1630
1631 /* vim: set ts=4 sw=4 et: */