clean some tests
[calc.git] / parser.c
CommitLineData
bc97a989 1#include <malloc.h>
f2927108 2#include <math.h>
87621fe1 3#include <stdio.h>
bc97a989 4#include <stdlib.h>
b9c1c40d 5#include <string.h>
bc97a989
LM
6
7#include "debug.h"
bc97a989
LM
8
9#include "parser.h"
10
5075f6ea
LM
11/* global variables */
12
13double answer = 0;
14
f438579a
LM
15#define DEFAULT_STORAGE_SIZE 10
16int storage_size = -1;
f438579a
LM
17double *storage = NULL;
18
1e292005
LM
19int argument_size = 0;
20double *argument = NULL;
21
a9a3da22
LM
22int stack_size = 0;
23double *stack = NULL;
24
f438579a 25#define DEFAULT_FORMAT "=> %.6g\n"
2a5ec9d1 26char *format = NULL;
9b759869 27char *minform = NULL;
715580ff 28
c7cbb833 29workspace_t *programs = NULL;
05aabb97 30int nb_programs = 0;
c7cbb833 31
bc97a989
LM
32/* compare codes */
33
34int codecmp (char *ref, char *str)
35{
36 int sig;
37
38 while (*ref != '\0') {
0b9cc9b0
LM
39 if (*ref == '\t') {
40 sig = (*str == '.') ? -1 : ((*str >= '0') && (*str <= '9'));
41 } else {
42 sig = *str - *ref;
43 }
bc97a989
LM
44 if (sig != 0) {
45 return (sig > 0) ? 1 : -1;
46 }
0b9cc9b0
LM
47 str++;
48 ref++;
bc97a989
LM
49 }
50
51 return 0;
52}
53
6f14d1cc 54/* calloc or die function */
bc97a989 55
6f14d1cc 56void *callocordie (size_t count, size_t size)
bc97a989 57{
d59a8079
LM
58 if (count * size == 0) {
59 return NULL;
60 }
6f14d1cc 61 void *new = calloc (count, size);
bc97a989 62 if (new == NULL) {
04d68907 63 VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n"));
d32ea0b0 64 exit (1);
bc97a989 65 }
6f14d1cc
LM
66 return new;
67}
68
69/* allocate new element */
70
71element_t *newelement (func_t function, int nbops, int prio)
72{
73 element_t *new = (element_t *) callocordie (1, sizeof (element_t));
62d56da6 74 if (nbops) {
6f14d1cc 75 new->ops = (element_t **) callocordie (nbops, sizeof (element_t *));
0c95a3d3 76 }
bc97a989
LM
77 new->func = function;
78 new->nbops = nbops;
11cda8d7 79 new->prio = prio;
bc97a989
LM
80
81 return new;
82}
83
031d7bba
LM
84/* desallocate element */
85
86void delelement (element_t *root)
87{
031d7bba 88 if ((root != NULL) && (root != ERROR_OP)) {
0c95a3d3 89 int i;
031d7bba 90 for (i = 0; i < root->nbops; i++) {
f50ed10b 91 delelement (root->ops[i]);
031d7bba 92 }
0c95a3d3
LM
93 if (root->nbops) {
94 free (root->ops);
95 }
031d7bba
LM
96 free (root);
97 }
98}
99
2a688642
LM
100/* duplicate element */
101
102element_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);
2a688642
LM
111 tmp->value = root->value;
112 for (i = 0; i < root->nbops; i++) {
113 tmp->ops[i] = dupelement (root->ops[i]);
2a688642
LM
114 }
115 return tmp;
116}
117
bc97a989
LM
118/* functions */
119
a9a3da22
LM
120#define MAX_ARGS 100
121
ca3e2a2f 122#define NB_OPERATORS 14
bc97a989 123keyword_t operators[NB_OPERATORS] = {
11cda8d7
LM
124 { "+\t", Add, 2, 1, 1},
125 { "-\t", Sub, 2, 1, 1},
126 { "*", Mul, 2, 1, 2},
127 { "/", Div, 2, 1, 2},
c47a9298 128 { "%", Mod, 2, 1, 3},
7fe742c9 129 { "^", Pow, 2, 1, 4},
ca3e2a2f
LM
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}
bc97a989
LM
138};
139
226557a3 140#define NB_FUNCTIONS 50
bc97a989 141keyword_t functions[NB_FUNCTIONS] = {
c47a9298
LM
142 { "sqrt", Sqr, 1, 4, 5},
143 { "pow", Pow, 2, 3, 5},
144 { "cos", Cos, 1, 3, 5},
145 { "sin", Sin, 1, 3, 5},
9e52bbc5
LM
146 { "tan", Tan, 1, 3, 5},
147 { "acos", Acos, 1, 4, 5},
148 { "asin", Asin, 1, 4, 5},
471da7c9 149 { "atan", Atan, 1, 4, 5},
2a986c8f 150 { "ln", Ln, 1, 2, 5},
89cf0955 151 { "log", Log, 1, 3, 5},
9e52bbc5 152 { "exp", Exp, 1, 3, 5},
72b7d4bc
LM
153 { "erfc", Erfc, 1, 4, 5},
154 { "erf", Erf, 1, 3, 5},
9e52bbc5
LM
155 { "abs", Abs, 1, 3, 5},
156 { "floor", Floor, 1, 5, 5},
157 { "ceil", Ceil, 1, 4, 5},
2a688642 158 { "sto", Store, 2, 3, 5},
6ba1dd0f 159 { "rcl", Recall, 1, 3, 5},
a8cf32ba
LM
160 { "inc", Inc, 1, 3, 5},
161 { "dec", Dec, 1, 3, 5},
ca3e2a2f 162 { "disp", Disp, 0, 4, 9},
1e292005 163 { "mem", Mem, 1, 3, 5},
143f91ae 164 { "clr", Clear, 0, 3, 9},
ca3e2a2f
LM
165 { "quit", Quit, 0, 4, 9},
166 { "help", Help, 0, 4, 9},
94b4e517 167 { "!", Not, 1, 1, 6},
2a688642 168 { "cond", Cond, 3, 4, 5},
715580ff 169 { "while", While, 2, 5, 5},
c7cbb833 170 { "print", Print, 1, 5, 5},
1e292005
LM
171 { "prog", Prog, 2, 4, 9},
172 { "arg", Arg, 1, 3, 5},
a9a3da22 173 { "call", Call, MAX_ARGS, 4, 5},
c7cbb833
LM
174 { "ls", List, 0, 2, 9},
175 { "edit", Edit, 1, 4, 9},
a9a3da22
LM
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},
4747e9a1 182 { "set", Set, MAX_ARGS, 3, 5},
226557a3
LM
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},
471da7c9
LM
192};
193
5075f6ea 194#define NB_CONSTANTS 3
471da7c9 195keyword_t constants[NB_CONSTANTS] = {
5075f6ea
LM
196 { "ans", Ans, 0, 3, 5},
197 { "e", E, 0, 1, 5},
198 { "pi", Pi, 0, 2, 5}
bc97a989
LM
199};
200
db660e60
LM
201#define NB_SYMBOLS 4
202char *symbols[NB_SYMBOLS] = {
203 "(", ")", "{", "}"
204};
205
d2ff8478
LM
206/* subparser function */
207
208element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, int prio)
209{
210 element_t *new = newelement (func, nbops, prio);
d2ff8478
LM
211 new->ops[0] = *proot;
212 new->ops[1] = parser (*pstr, pstr, new->prio);
686c4bc2 213 if ((new->ops[1] == NULL) || ((new->ops[1] != ERROR_OP) && (new->ops[1]->prio == 9))) {
67b13e3d
LM
214 delelement (new->ops[1]);
215 new->ops[1] = ERROR_OP;
216 }
d2ff8478 217 if (new->ops[1] == ERROR_OP) {
031d7bba
LM
218 delelement (new);
219 *proot = NULL;
d2ff8478
LM
220 return ERROR_OP;
221 }
3b4b0bbe 222 *proot = newelement (Val, 1, 5);
d2ff8478
LM
223 (*proot)->ops[0] = new;
224
225 return *proot;
226}
227
bc97a989
LM
228/* parser function */
229
ef37d966 230element_t *parser (char *str, char **next, int prio)
0b489a77 231{
bc97a989 232 element_t *root = NULL;
779282bb 233 char *string = str;
85b4a72c 234 int i;
bc97a989 235
04d68907 236 VERBOSE (DEBUG, fprintf (stdout, "Starting parsing\n"));
49223129 237
bc97a989
LM
238 /* main loop */
239 while (*str != '\0') {
240 int found = 0;
241 element_t *new = NULL;
04d68907 242 VERBOSE (INFO, fprintf (stdout, "Processing: %s\n", str));
bc97a989 243
2d0cd54c
LM
244 /* end without printing */
245
246 if (*str == ';') {
247 if (root) {
248 root->hidden = 1;
249 }
250 break;
251 }
252
bc97a989
LM
253 /* skip spaces and tabs */
254
255 if ((*str == ' ') || (*str == '\t')) {
256 str++;
257 continue;
258 }
259
124da7fd
LM
260 /* check for open brace */
261
262 if (*str == '{') {
263 VERBOSE (DEBUG, fprintf (stdout, "start processing brace\n"));
62d56da6 264 if (root != NULL) {
124da7fd
LM
265 delelement (root);
266 return ERROR_OP;
267 }
f50ed10b 268 root = newelement (Code, 0, 5);
124da7fd
LM
269
270 do {
124da7fd
LM
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 }
7929d368 276 if (new == ERROR_OP) {
124da7fd 277 delelement (root);
62d56da6 278 return ERROR_OP;
124da7fd 279 }
1e292005 280 element_t *newcode = newelement (Code, root->nbops + 1, 5);
f50ed10b 281 for (i = 0; i < root->nbops; i++) {
1e292005 282 newcode->ops[i] = root->ops[i];
f50ed10b 283 root->ops[i] = NULL;
124da7fd 284 }
1e292005 285 newcode->ops[root->nbops] = new;
f50ed10b 286 delelement (root);
1e292005 287 root = newcode;
124da7fd
LM
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
85b4a72c 299 /* check for open bracket */
0b489a77 300
0b489a77 301 if (*str == '(') {
04d68907 302 VERBOSE (DEBUG, fprintf (stdout, "start processing bracket\n"));
0b489a77 303 if (root) {
85b4a72c
LM
304 do {
305 found = 0;
ef37d966 306 new = parser (str + 1, &str, 0);
686c4bc2 307 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
67b13e3d
LM
308 delelement (new);
309 new = ERROR_OP;
310 }
686c4bc2 311 if ((new == NULL) || (new == ERROR_OP)) {
031d7bba 312 delelement (root);
85b4a72c
LM
313 return ERROR_OP;
314 }
315 for (i = 0; i < root->nbops; i++) {
316 if (root->ops[i] == NULL) {
0b489a77
LM
317 root->ops[i] = new;
318 found = 1;
319 break;
320 }
321 }
85b4a72c 322 if (!found) {
031d7bba
LM
323 delelement (new);
324 delelement (root);
85b4a72c
LM
325 return ERROR_OP;
326 }
327 } while (*str == ',');
328 } else {
3b4b0bbe 329 root = newelement (Val, 1, 5);
ef37d966 330 new = parser (str + 1, &str, 0);
686c4bc2 331 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
67b13e3d
LM
332 delelement (new);
333 new = ERROR_OP;
334 }
686c4bc2 335 if ((new == NULL) || (new == ERROR_OP) || (*str == ',')) {
031d7bba
LM
336 delelement (new);
337 delelement (root);
efdfb543
LM
338 return ERROR_OP;
339 }
85b4a72c 340 root->ops[0] = new;
0b489a77 341 }
3c0db5bc
LM
342 if (*str != ')') {
343 delelement (root);
344 return ERROR_OP;
345 }
85b4a72c 346 str++;
04d68907 347 VERBOSE (DEBUG, fprintf (stdout, "stop processing bracket\n"));
efdfb543 348 continue;
49223129 349 }
85b4a72c 350
124da7fd 351 /* check for closing bracket, closing brace or koma */
85b4a72c 352
124da7fd 353 if ((*str == ')') || (*str == '}') || (*str == ',')) {
45a631a8
LM
354 if (prio == -9) {
355 delelement (root);
356 return ERROR_OP;
357 }
49223129 358 if (next != NULL) {
85b4a72c 359 *next = str;
49223129
LM
360 }
361 return root;
0b489a77
LM
362 }
363
bc97a989
LM
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) {
04d68907 369 VERBOSE (DEBUG, fprintf (stdout, "start processing operator\n"));
a28ab26a
LM
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) {
ef37d966 375 if ((prio) && (prio > operator->prio)) {
04d68907 376 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
ef37d966
LM
377 *next = str;
378 return root;
379 }
380 str += operator->offset;
04d68907 381 VERBOSE (INFO, fprintf (stdout, "Oper: %d\n", operator->func));
d2ff8478 382 if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) {
031d7bba 383 delelement (root);
ef37d966 384 return ERROR_OP;
11cda8d7 385 }
3b4b0bbe 386 } else if (*str == '-') {
a28ab26a 387 root = newelement (Sig, 1, 6);
49223129 388 } else {
0b489a77 389 return ERROR_OP;
bc97a989 390 }
bc97a989 391 found = 1;
04d68907 392 VERBOSE (DEBUG, fprintf (stdout, "stop processing operator\n"));
bc97a989
LM
393 break;
394 }
395 }
396 if (found) {
bc97a989
LM
397 continue;
398 }
49223129 399
bc97a989
LM
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) {
04d68907 405 VERBOSE (DEBUG, fprintf (stdout, "start processing function\n"));
bc97a989 406 if (root == NULL) {
04d68907 407 VERBOSE (INFO, fprintf (stdout, "Func: %d\n", function->func));
d32ea0b0 408 root = newelement (function->func, function->nbops, function->prio);
031d7bba
LM
409 } else {
410 delelement (root);
0b489a77 411 return ERROR_OP;
bc97a989
LM
412 }
413 str += function->offset;
414 found = 1;
04d68907 415 VERBOSE (DEBUG, fprintf (stdout, "stop processing function\n"));
bc97a989
LM
416 break;
417 }
418 }
419 if (found) {
bc97a989
LM
420 continue;
421 }
422
471da7c9
LM
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) {
5075f6ea 430 VERBOSE (INFO, fprintf (stdout, "Const: %d\n", constant->func));
d32ea0b0 431 root = newelement (constant->func, constant->nbops, constant->prio);
471da7c9
LM
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
bc97a989
LM
446 /* look for number */
447
0b9cc9b0
LM
448 if (((*str >= '0') && (*str <= '9')) ||
449 (*str == '.') || (*str == '+') || (*str == '-')) {
04d68907 450 VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
bc97a989 451 char *pt;
fd88e359 452 double value = strtod (str, &pt);
04d68907 453 VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
bc97a989 454 if (str != pt) {
ce6627f2 455 if ((root == NULL) || (root->prio == 6)) {
3b4b0bbe 456 new = newelement (Val, 1, 5);
c47a9298 457 new->value = value;
ce6627f2
LM
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 }
c47a9298 474 str = pt;
32741902
LM
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) {
031d7bba 482 delelement (root);
0b489a77 483 return ERROR_OP;
bc97a989 484 }
0b9cc9b0 485 } else {
031d7bba 486 delelement (root);
0b9cc9b0 487 return ERROR_OP;
bc97a989 488 }
bc97a989
LM
489 found = 1;
490 }
04d68907 491 VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
bc97a989
LM
492 }
493
494 /* error */
495
496 if (!found) {
031d7bba 497 delelement (root);
0b489a77 498 return ERROR_OP;
bc97a989
LM
499 }
500
501 }
502
49223129
LM
503 if (next != NULL) {
504 *next = str;
505 }
031d7bba 506
779282bb 507 /* save string */
0a8a1de3
ML
508 if (root != NULL) {
509 root->string = string;
510 }
779282bb 511
bc97a989
LM
512 return root;
513}
514
515/* print element tree */
516
517void print_element (element_t *root, int level)
518{
519 char *func = NULL;
520 int i;
521
49223129 522 if ((root == NULL) || (root == ERROR_OP)) {
bc97a989 523 return;
49223129
LM
524 }
525
bc97a989 526 for (i = 0; i < level; i++) {
04d68907 527 fprintf (stdout, " ");
bc97a989
LM
528 }
529
530 switch (root->func) {
531 case Val: func = "Value"; break;
89cf0955 532 case Sig: func = "Sign"; break;
bc97a989
LM
533 case Add: func = "Addition"; break;
534 case Sub: func = "Subtraction"; break;
535 case Mul: func = "Multiplication"; break;
536 case Div: func = "Division"; break;
c47a9298 537 case Mod: func = "Modulo"; break;
bc97a989
LM
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;
9e52bbc5
LM
542 case Tan: func = "Tangent"; break;
543 case Acos: func = "Arc Cosine"; break;
544 case Asin: func = "Arc Sine"; break;
471da7c9 545 case Atan: func = "Arc Tangent"; break;
532af887 546 case Ln: func = "Logarithm (natural)"; break;
2a986c8f 547 case Log: func = "Logarithm (10 base)"; break;
bc97a989 548 case Exp: func = "Exponantial"; break;
72b7d4bc
LM
549 case Erfc: func = "Complementary Error Function"; break;
550 case Erf: func = "Error Function"; break;
9e52bbc5
LM
551 case Abs: func = "Absolute value"; break;
552 case Ceil: func = "Ceil value"; break;
553 case Floor: func = "Floor value"; break;
6ba1dd0f
LM
554 case Store: func = "Store"; break;
555 case Recall: func = "Recall"; break;
a8cf32ba
LM
556 case Inc: func = "Increase"; break;
557 case Dec: func = "Decrease"; break;
6ba1dd0f 558 case Disp: func = "Display"; break;
f438579a 559 case Mem: func = "Memory"; break;
143f91ae 560 case Clear: func = "Clear"; break;
471da7c9
LM
561 case Quit: func = "Quit"; break;
562 case Help: func = "Help"; break;
5075f6ea 563 case Ans: func = "Ans"; break;
471da7c9
LM
564 case Pi: func = "Pi"; break;
565 case E: func = "E"; break;
7fe742c9
LM
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;
ca3e2a2f
LM
572 case And: func = "And"; break;
573 case Or: func = "Or"; break;
574 case Not: func = "Not"; break;
94b4e517 575 case Cond: func = "Condition"; break;
2a688642 576 case While: func = "While"; break;
05aabb97 577 case Code: func = "Code"; break;
715580ff 578 case Print: func = "Print"; break;
c7cbb833 579 case Prog: func = "Program"; break;
1e292005 580 case Arg: func = "Argument"; break;
c7cbb833
LM
581 case Call: func = "Call"; break;
582 case List: func = "List"; break;
583 case Edit: func = "Edit"; break;
584 case Del: func = "Del"; break;
a9a3da22
LM
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;
226557a3
LM
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;
bc97a989
LM
600 }
601
04d68907 602 fprintf (stdout, "Function: %s\n", func);
bc97a989 603
85b4a72c 604 if ((root->func == Val) && (root->ops[0] == NULL)) {
bc97a989 605 for (i = 0; i < level; i++) {
04d68907 606 fprintf (stdout, " ");
bc97a989 607 }
04d68907 608 fprintf (stdout, "value: %f\n", root->value);
bc97a989
LM
609 } else {
610 for (i = 0; i < root->nbops; i++) {
611 print_element (root->ops[i], level + 1);
612 }
613 }
614}
615
6ba1dd0f
LM
616/* storage functions */
617
f438579a
LM
618void 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;
6f14d1cc 624 tmp = (double *) callocordie (nb, sizeof (double));
f438579a
LM
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
3639df66 636double store (int index, double value)
6ba1dd0f 637{
f438579a
LM
638 if (storage_size == -1) {
639 memory (DEFAULT_STORAGE_SIZE);
640 }
641 if ((index > 0) && (index <= storage_size)) {
3639df66 642 storage[index - 1] = value;
6ba1dd0f 643 } else {
9b759869 644 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
6ba1dd0f 645 }
3639df66 646 return value;
6ba1dd0f
LM
647}
648
649double recall (int index)
650{
f438579a
LM
651 if (storage_size == -1) {
652 memory (DEFAULT_STORAGE_SIZE);
653 }
654 if ((index > 0) && (index <= storage_size)) {
6ba1dd0f
LM
655 return storage[index - 1];
656 } else {
9b759869 657 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
6ba1dd0f
LM
658 }
659 return 0;
660}
661
a8cf32ba
LM
662double increase (int index)
663{
f438579a
LM
664 if (storage_size == -1) {
665 memory (DEFAULT_STORAGE_SIZE);
666 }
667 if ((index > 0) && (index <= storage_size)) {
a8cf32ba
LM
668 return storage[index - 1]++;
669 } else {
9b759869 670 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
a8cf32ba
LM
671 }
672 return 0;
673}
674
675double decrease (int index)
676{
f438579a
LM
677 if (storage_size == -1) {
678 memory (DEFAULT_STORAGE_SIZE);
679 }
680 if ((index > 0) && (index <= storage_size)) {
a8cf32ba
LM
681 return storage[index - 1]--;
682 } else {
9b759869 683 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
a8cf32ba
LM
684 }
685 return 0;
686}
687
6ba1dd0f
LM
688void display (void)
689{
690 int i;
f438579a
LM
691 if (storage_size == -1) {
692 memory (DEFAULT_STORAGE_SIZE);
693 }
6ba1dd0f 694 fprintf (stdout, "storage:");
f438579a 695 for (i = 0; i < storage_size; i++) {
9b759869
LM
696 fprintf (stdout, " ");
697 fprintf (stdout, minform, storage[i]);
6ba1dd0f
LM
698 }
699 fprintf (stdout, "\n");
700}
701
143f91ae
LM
702void clear ()
703{
704 int i;
705 for (i = 0; i < storage_size; i++) {
706 storage[i] = 0;
707 }
708}
709
2a688642
LM
710/* While do function */
711
712double 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"));
2a688642
LM
718 while (1) {
719 VERBOSE (DEBUG, fprintf (stdout, "loop...\n"));
720
721 temp = dupelement (cond);
523841a1
ML
722 double test = evaluate_element (temp, 0);
723 delelement (temp);
724 if (!test) {
2a688642
LM
725 break;
726 }
727 if (action) {
728 temp = dupelement (action);
729 ret = evaluate_element (temp, 0);
523841a1 730 delelement (temp);
2a688642
LM
731 }
732 }
733
734 VERBOSE (DEBUG, fprintf (stdout, "ending while loop\n"));
735
736 return ret;
737}
738
124da7fd
LM
739/* program function */
740
05aabb97 741double execute_code (element_t **prog, int nbcalls)
124da7fd
LM
742{
743 double ret = 0;
744 int i;
745 for (i = 0; i < nbcalls; i++) {
746 ret = evaluate_element (prog[i], 0);
124da7fd
LM
747 }
748 return ret;
749}
750
2a5ec9d1
LM
751/* print function */
752
753void set_format (char *prompt, int precision)
754{
755 char buffer[128] = {0};
2a5ec9d1 756 free_format ();
9b759869 757 sprintf (buffer, "%s%%.%dg\n", prompt, precision);
2a5ec9d1 758 format = strdup (buffer);
9b759869
LM
759 sprintf (buffer, "%%.%dg", precision);
760 minform = strdup (buffer);
2a5ec9d1
LM
761}
762
763void free_format ()
764{
765 if (format) {
766 free (format);
767 format = NULL;
768 }
9b759869
LM
769 if (minform) {
770 free (minform);
771 minform = NULL;
772 }
2a5ec9d1
LM
773}
774
775double print (double value)
776{
f438579a 777 fprintf (stdout, format ? format : DEFAULT_FORMAT, value);
2a5ec9d1
LM
778 fflush (stdout);
779 return value;
780}
781
89cf0955
LM
782/* quit function */
783
784void quit (void)
785{
04d68907 786 fprintf (stdout, "bye\n");
89cf0955
LM
787 exit (0);
788}
789
c7cbb833
LM
790/* program function */
791
1e292005 792void prog (int id, element_t *root)
05aabb97
LM
793{
794 int i, n = -1;
795
796 if (programs == NULL) {
797
798 /* initial memory allocation */
6f14d1cc 799 programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
05aabb97
LM
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++;
6f14d1cc
LM
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;
05aabb97
LM
820 } else {
821
822 /* clean old program */
823 if ((programs + n)->storage) {
824 free ((programs + n)->storage);
825 }
a9a3da22
LM
826 if ((programs + n)->stack) {
827 free ((programs + n)->stack);
828 }
05aabb97
LM
829 if ((programs + n)->root) {
830 delelement ((programs + n)->root);
831 }
2e34899a
LM
832 if ((programs + n)->string) {
833 free ((programs + n)->string);
0a8a1de3 834 (programs + n)->string = NULL;
2e34899a 835 }
05aabb97
LM
836 }
837 }
838
839 /* set program */
840 (programs + n)->id = id;
841 (programs + n)->answer = 0;
1e292005
LM
842 (programs + n)->storage = NULL;
843 (programs + n)->storage_size = 0;
a9a3da22
LM
844 (programs + n)->stack = NULL;
845 (programs + n)->stack_size = 0;
e7d5c144 846 (programs + n)->root = dupelement (root);
05aabb97 847}
c7cbb833 848
1e292005
LM
849double 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
860double call (int id, int nbargs, element_t **args)
c7cbb833 861{
05aabb97 862 workspace_t tmp = {0};
1e292005 863 int i, l, n = -1;
05aabb97
LM
864 double ret = 0;
865
866 if (programs) {
e7d5c144
LM
867
868 /* look for program */
05aabb97 869 for (i = 0; i < nb_programs; i++) {
e7d5c144 870 if ((programs + i)->id == id) {
05aabb97
LM
871 n = i;
872 break;
873 }
874 }
d59a8079
LM
875 }
876 if (n == -1) {
877 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
878 return 0;
879 }
05aabb97 880
d59a8079
LM
881 /* store context */
882 tmp.answer = answer;
1e292005
LM
883 tmp.argument = argument;
884 tmp.argument_size = argument_size;
d59a8079
LM
885 tmp.storage = storage;
886 tmp.storage_size = storage_size;
a9a3da22
LM
887 tmp.stack = stack;
888 tmp.stack_size = stack_size;
05aabb97 889
d59a8079
LM
890 /* change context */
891 answer = 0;
892 storage = (programs + n)->storage;
893 storage_size = (programs + n)->storage_size;
1e292005
LM
894 argument = NULL;
895 argument_size = 0;
a9a3da22
LM
896 stack = (programs + n)->stack;
897 stack_size = (programs + n)->stack_size;
1e292005
LM
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;
d59a8079
LM
906 }
907
908 /* evaluate program */
909 element_t *elements = dupelement ((programs + n)->root);
910 ret = evaluate_element (elements, 0);
523841a1 911 delelement (elements);
4747e9a1
LM
912 (programs + n)->answer = answer;
913 (programs + n)->storage = storage;
914 (programs + n)->storage_size = storage_size;
1e292005
LM
915 if (argument) {
916 free (argument);
917 }
4747e9a1
LM
918 (programs + n)->stack = stack;
919 (programs + n)->stack_size = stack_size;
d59a8079
LM
920
921 /* restore context */
922 answer = tmp.answer;
923 storage = tmp.storage;
4747e9a1 924 storage_size = tmp.storage_size;
1e292005
LM
925 argument = tmp.argument;
926 argument_size = tmp.argument_size;
4747e9a1 927 stack = tmp.stack;
a9a3da22 928 stack_size = tmp.stack_size;
05aabb97
LM
929
930 return ret;
c7cbb833
LM
931}
932
933void list ()
05aabb97
LM
934{
935 int i;
d59a8079
LM
936 fprintf (stdout, "programs:");
937 for (i = 0; i < nb_programs; i++) {
938 fprintf (stdout, " %d", (programs + i)->id);
05aabb97 939 }
d59a8079 940 fprintf (stdout, "\n");
05aabb97 941}
c7cbb833
LM
942
943void edit (int id)
2e34899a
LM
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 */
779282bb 963 fprintf (stdout, "edit: %s\n", (programs + n)->string);
2e34899a
LM
964}
965
779282bb 966void savestring (int id, char *string)
2e34899a
LM
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 }
2e34899a 980
1b068216
LM
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
226557a3
LM
990 if (string) {
991 (programs + n)->string = strdup (string);
992 }
2e34899a 993}
c7cbb833
LM
994
995void del (int id)
d59a8079
LM
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 }
a9a3da22
LM
1018 if ((programs + n)->stack) {
1019 free ((programs + n)->stack);
1020 }
d59a8079
LM
1021 if ((programs + n)->root) {
1022 delelement ((programs + n)->root);
1023 }
2e34899a
LM
1024 if ((programs + n)->string) {
1025 free ((programs + n)->string);
1026 }
d59a8079
LM
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}
c7cbb833 1040
a9a3da22
LM
1041/* stack management */
1042
1043double 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
1054double length ()
1055{
1056 return stack_size;
1057}
1058
1059double 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
1074double 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
1086double 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
1103double 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
1121void 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
226557a3
LM
1132/* stack functions */
1133
1134double 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
1151double 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
1165double 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
1182void 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
1205double 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
1221double 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
1235double 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
1249double 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
89cf0955
LM
1266/* help message */
1267
1268void help (void)
1269{
04d68907 1270 fprintf (stdout, "calc is a simple calculator\n\n");
0e1004e3 1271 fprintf (stdout, "arithmetic op.:");
94b4e517 1272 fprintf (stdout, " + - * / %% ^\n");
0e1004e3 1273 fprintf (stdout, "comparison op.:");
94b4e517 1274 fprintf (stdout, " == != >= <= > <\n");
0e1004e3 1275 fprintf (stdout, "logical op.:");
94b4e517 1276 fprintf (stdout, " & | !\n");
0e1004e3 1277 fprintf (stdout, "mathematic func.:");
347b66f8 1278 fprintf (stdout, " exp ln log pow sqrt\n");
0e1004e3 1279 fprintf (stdout, "trigonometric func.:");
347b66f8 1280 fprintf (stdout, " acos asin atan cos sin tan\n");
72b7d4bc
LM
1281 fprintf (stdout, "error functions:");
1282 fprintf (stdout, " erf erfc\n");
0e1004e3 1283 fprintf (stdout, "miscellaneous func.:");
9e52bbc5 1284 fprintf (stdout, " abs ceil floor\n");
0e1004e3 1285 fprintf (stdout, "storage func.:");
347b66f8 1286 fprintf (stdout, " clear dec disp inc mem rcl sto\n");
0e1004e3 1287 fprintf (stdout, "control flow prim.:");
347b66f8 1288 fprintf (stdout, " cond print while {} ;\n");
0e1004e3 1289 fprintf (stdout, "program management:");
1e292005 1290 fprintf (stdout, " arg call del edit ls prog\n");
a9a3da22
LM
1291 fprintf (stdout, "stack management:");
1292 fprintf (stdout, " get len pop push put set show\n");
226557a3
LM
1293 fprintf (stdout, "stack func.:");
1294 fprintf (stdout, " max mean med min ord prod sum var\n");
0e1004e3 1295 fprintf (stdout, "control management:");
347b66f8 1296 fprintf (stdout, " help quit\n");
0e1004e3 1297 fprintf (stdout, "constants:");
347b66f8 1298 fprintf (stdout, " ans e pi\n");
89cf0955 1299}
3b4b0bbe 1300
f2927108
LM
1301/* evaluate element tree */
1302
89cf0955
LM
1303#define MASK_SUB 0x1
1304#define MASK_DIV 0x2
1305
3b4b0bbe 1306double evaluate_element (element_t *root, char mask)
f2927108
LM
1307{
1308 double op0 = 0, op1 = 0;
3b4b0bbe 1309 char nextmask = mask;
e7d5c144 1310 int i, nb;
f2927108
LM
1311
1312 if ((root == NULL) || (root == ERROR_OP)) {
04d68907 1313 VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n"));
f2927108
LM
1314 return 0;
1315 }
1316
3b4b0bbe
LM
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
f2927108
LM
1337 switch (root->func) {
1338 case Val:
3b4b0bbe
LM
1339 case Sig:
1340 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
f2927108
LM
1341 break;
1342 case Add:
1343 case Sub:
1344 case Mul:
1345 case Div:
c47a9298 1346 case Mod:
f2927108 1347 case Pow:
3639df66 1348 case Store:
7fe742c9
LM
1349 case Equal:
1350 case Diff:
1351 case Ge:
1352 case Le:
1353 case Gt:
1354 case Lt:
ca3e2a2f
LM
1355 case And:
1356 case Or:
f2927108 1357 if (root->ops[1]) {
3b4b0bbe 1358 op1 = evaluate_element (root->ops[1], nextmask);
3639df66 1359 } else if (root->func != Store) {
04d68907 1360 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
f2927108
LM
1361 return 0;
1362 }
1363 /* fallthrough */
1364 case Sqr:
1365 case Cos:
1366 case Sin:
9e52bbc5
LM
1367 case Tan:
1368 case Acos:
1369 case Asin:
471da7c9 1370 case Atan:
2a986c8f 1371 case Ln:
f2927108
LM
1372 case Log:
1373 case Exp:
72b7d4bc
LM
1374 case Erfc:
1375 case Erf:
9e52bbc5
LM
1376 case Abs:
1377 case Ceil:
1378 case Floor:
6ba1dd0f 1379 case Recall:
a8cf32ba
LM
1380 case Inc:
1381 case Dec:
ca3e2a2f 1382 case Not:
f438579a 1383 case Mem:
94b4e517 1384 case Cond:
1e292005
LM
1385 case Prog:
1386 case Arg:
c7cbb833 1387 case Call:
c7cbb833
LM
1388 case Edit:
1389 case Del:
a9a3da22 1390 case Get:
f2927108 1391 if (root->ops[0]) {
3b4b0bbe 1392 op0 = evaluate_element (root->ops[0], 0);
f2927108 1393 } else {
04d68907 1394 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
f2927108
LM
1395 return 0;
1396 }
89cf0955 1397 break;
6ba1dd0f 1398 case Disp:
143f91ae 1399 case Clear:
471da7c9
LM
1400 case Quit:
1401 case Help:
5075f6ea 1402 case Ans:
471da7c9
LM
1403 case Pi:
1404 case E:
05aabb97 1405 case Code:
e7d5c144 1406 case List:
a9a3da22
LM
1407 case Length:
1408 case Pop:
1409 case Set:
1410 case Show:
226557a3
LM
1411 case Median:
1412 case Order:
1413 case Prod:
1414 case Sum:
09d87cae 1415 break;
2a688642 1416 case While:
09d87cae
LM
1417 if (root->ops[0] == NULL) {
1418 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1419 return 0;
1420 }
89cf0955 1421 break;
a9a3da22 1422 case Push:
715580ff
LM
1423 case Print:
1424 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
1425 break;
a9a3da22
LM
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;
226557a3
LM
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 }
f2927108
LM
1443 }
1444
1445 switch (root->func) {
3b4b0bbe
LM
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;
c47a9298 1452 case Mod: return fmod (op0, op1);
f2927108
LM
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);
9e52bbc5
LM
1457 case Tan: return tan (op0);
1458 case Acos: return acos (op0);
1459 case Asin: return asin (op0);
471da7c9 1460 case Atan: return atan (op0);
2a986c8f
LM
1461 case Ln: return log (op0);
1462 case Log: return log10 (op0);
f2927108 1463 case Exp: return exp (op0);
72b7d4bc
LM
1464 case Erfc: return erfc (op0);
1465 case Erf: return erf (op0);
9e52bbc5
LM
1466 case Abs: return fabs (op0);
1467 case Ceil: return ceil (op0);
1468 case Floor: return floor (op0);
3639df66 1469 case Store: return store ((int)op0, (op1) ? op1 : answer);
6ba1dd0f 1470 case Recall: return recall ((int)op0);
a8cf32ba
LM
1471 case Inc: return increase ((int)op0);
1472 case Dec: return decrease ((int)op0);
6ba1dd0f 1473 case Disp: display (); break;
f438579a 1474 case Mem: memory ((int)op0); break;
143f91ae 1475 case Clear: clear (); break;
471da7c9
LM
1476 case Quit: quit (); break;
1477 case Help: help (); break;
5075f6ea 1478 case Ans: return answer;
471da7c9
LM
1479 case Pi: return M_PI;
1480 case E: return M_E;
7fe742c9
LM
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;
ca3e2a2f
LM
1487 case And: return (op0 != 0) && (op1 != 0);
1488 case Or: return (op0 != 0) || (op1 != 0);
1489 case Not: return (op0 == 0);
94b4e517
LM
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 }
2a688642 1498 case While: return while_do (root->ops[0], root->ops[1]);
05aabb97 1499 case Code: return execute_code (root->ops, root->nbops);
2a5ec9d1 1500 case Print: return print (op0);
779282bb 1501 case Prog:
1e292005 1502 prog ((int)op0, root->ops[1]);
779282bb
LM
1503 savestring ((int)op0, root->string);
1504 break;
1e292005 1505 case Arg: return arg ((int)op0);
e7d5c144
LM
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);
c7cbb833
LM
1513 case List: list (); break;
1514 case Edit: edit ((int)op0); break;
05aabb97 1515 case Del: del ((int)op0); break;
a9a3da22
LM
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;
226557a3
LM
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 ();
f2927108
LM
1556 }
1557
1558 return 0;
1559}
1560
b9c1c40d
LM
1561char **generate_completion_list ()
1562{
db660e60 1563 int i, j, l = 0;
6f14d1cc 1564 char **list = (char **) callocordie (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *));
b9c1c40d 1565
db660e60
LM
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 }
d8f4df0f
LM
1573 if (list[l] != NULL) {
1574 l++;
db660e60 1575 }
db660e60
LM
1576 }
1577
b9c1c40d
LM
1578 for (i = 0; i < NB_FUNCTIONS; i++) {
1579 list[l] = strdup ((functions + i)->keyword);
d8f4df0f
LM
1580 if (list[l] != NULL) {
1581 l++;
b9c1c40d 1582 }
b9c1c40d
LM
1583 }
1584
1585 for (i = 0; i < NB_CONSTANTS; i++) {
1586 list[l] = strdup ((constants + i)->keyword);
d8f4df0f
LM
1587 if (list[l] != NULL) {
1588 l++;
b9c1c40d 1589 }
b9c1c40d
LM
1590 }
1591
db660e60
LM
1592 for (i = 0; i < NB_SYMBOLS; i++) {
1593 list[l] = strdup (symbols[i]);
d8f4df0f
LM
1594 if (list[l] != NULL) {
1595 l++;
db660e60 1596 }
db660e60
LM
1597 }
1598
b9c1c40d
LM
1599 return (list);
1600}
1601
1602void free_completion_list (char **list)
1603{
1604 int i;
1605
1606 if (list) {
3d3e6770 1607 for (i = 0; i < NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1; i++) {
b9c1c40d
LM
1608 if (list[i] != NULL) {
1609 free (list[i]);
1610 }
1611 }
1612 free (list);
1613 }
1614}
1615
1616
bc97a989 1617/* vim: set ts=4 sw=4 et: */