extend coverage test
[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"));
11cda8d7 370 if (root) {
ef37d966 371 if ((prio) && (prio > operator->prio)) {
04d68907 372 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
ef37d966
LM
373 *next = str;
374 return root;
375 }
376 str += operator->offset;
04d68907 377 VERBOSE (INFO, fprintf (stdout, "Oper: %d\n", operator->func));
d2ff8478 378 if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) {
031d7bba 379 delelement (root);
ef37d966 380 return ERROR_OP;
11cda8d7 381 }
3b4b0bbe 382 } else if (*str == '-') {
d32ea0b0 383 root = newelement (Sig, 1, 9);
49223129 384 } else {
0b489a77 385 return ERROR_OP;
bc97a989 386 }
bc97a989 387 found = 1;
04d68907 388 VERBOSE (DEBUG, fprintf (stdout, "stop processing operator\n"));
bc97a989
LM
389 break;
390 }
391 }
392 if (found) {
bc97a989
LM
393 continue;
394 }
49223129 395
bc97a989
LM
396 /* look for functions */
397
398 for (i = 0; i < NB_FUNCTIONS; i++) {
399 keyword_t *function = functions + i;
400 if (codecmp (function->keyword, str) == 0) {
04d68907 401 VERBOSE (DEBUG, fprintf (stdout, "start processing function\n"));
bc97a989 402 if (root == NULL) {
04d68907 403 VERBOSE (INFO, fprintf (stdout, "Func: %d\n", function->func));
d32ea0b0 404 root = newelement (function->func, function->nbops, function->prio);
031d7bba
LM
405 } else {
406 delelement (root);
0b489a77 407 return ERROR_OP;
bc97a989
LM
408 }
409 str += function->offset;
410 found = 1;
04d68907 411 VERBOSE (DEBUG, fprintf (stdout, "stop processing function\n"));
bc97a989
LM
412 break;
413 }
414 }
415 if (found) {
bc97a989
LM
416 continue;
417 }
418
471da7c9
LM
419 /* look for constant */
420
421 for (i = 0; i < NB_CONSTANTS; i++) {
422 keyword_t *constant = constants + i;
423 if (codecmp (constant->keyword, str) == 0) {
424 VERBOSE (DEBUG, fprintf (stdout, "start processing constant\n"));
425 if (root == NULL) {
5075f6ea 426 VERBOSE (INFO, fprintf (stdout, "Const: %d\n", constant->func));
d32ea0b0 427 root = newelement (constant->func, constant->nbops, constant->prio);
471da7c9
LM
428 } else {
429 delelement (root);
430 return ERROR_OP;
431 }
432 str += constant->offset;
433 found = 1;
434 VERBOSE (DEBUG, fprintf (stdout, "stop processing constant\n"));
435 break;
436 }
437 }
438 if (found) {
439 continue;
440 }
441
bc97a989
LM
442 /* look for number */
443
0b9cc9b0
LM
444 if (((*str >= '0') && (*str <= '9')) ||
445 (*str == '.') || (*str == '+') || (*str == '-')) {
04d68907 446 VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
bc97a989 447 char *pt;
fd88e359 448 double value = strtod (str, &pt);
04d68907 449 VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
bc97a989 450 if (str != pt) {
ce6627f2 451 if ((root == NULL) || (root->prio == 6)) {
3b4b0bbe 452 new = newelement (Val, 1, 5);
c47a9298 453 new->value = value;
ce6627f2
LM
454 if (root == NULL) {
455 root = new;
456 } else {
457 for (i = 0; i < root->nbops; i++) {
458 if (root->ops[i] == NULL) {
459 root->ops[i] = new;
460 found = 1;
461 break;
462 }
463 }
464 if (!found) {
465 delelement (new);
466 delelement (root);
467 return ERROR_OP;
468 }
469 }
c47a9298 470 str = pt;
32741902
LM
471 } else if ((*str == '+') || (*str == '-')) {
472 if ((prio) && (prio > 1)) {
473 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
474 *next = str;
475 return root;
476 }
477 if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) {
031d7bba 478 delelement (root);
0b489a77 479 return ERROR_OP;
bc97a989 480 }
0b9cc9b0 481 } else {
031d7bba 482 delelement (root);
0b9cc9b0 483 return ERROR_OP;
bc97a989 484 }
bc97a989
LM
485 found = 1;
486 }
04d68907 487 VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
bc97a989
LM
488 }
489
490 /* error */
491
492 if (!found) {
031d7bba 493 delelement (root);
0b489a77 494 return ERROR_OP;
bc97a989
LM
495 }
496
497 }
498
49223129
LM
499 if (next != NULL) {
500 *next = str;
501 }
031d7bba 502
779282bb 503 /* save string */
0a8a1de3
ML
504 if (root != NULL) {
505 root->string = string;
506 }
779282bb 507
bc97a989
LM
508 return root;
509}
510
511/* print element tree */
512
513void print_element (element_t *root, int level)
514{
515 char *func = NULL;
516 int i;
517
49223129 518 if ((root == NULL) || (root == ERROR_OP)) {
bc97a989 519 return;
49223129
LM
520 }
521
bc97a989 522 for (i = 0; i < level; i++) {
04d68907 523 fprintf (stdout, " ");
bc97a989
LM
524 }
525
526 switch (root->func) {
527 case Val: func = "Value"; break;
89cf0955 528 case Sig: func = "Sign"; break;
bc97a989
LM
529 case Add: func = "Addition"; break;
530 case Sub: func = "Subtraction"; break;
531 case Mul: func = "Multiplication"; break;
532 case Div: func = "Division"; break;
c47a9298 533 case Mod: func = "Modulo"; break;
bc97a989
LM
534 case Pow: func = "Power"; break;
535 case Sqr: func = "Square Root"; break;
536 case Cos: func = "Cosine"; break;
537 case Sin: func = "Sine"; break;
9e52bbc5
LM
538 case Tan: func = "Tangent"; break;
539 case Acos: func = "Arc Cosine"; break;
540 case Asin: func = "Arc Sine"; break;
471da7c9 541 case Atan: func = "Arc Tangent"; break;
532af887 542 case Ln: func = "Logarithm (natural)"; break;
2a986c8f 543 case Log: func = "Logarithm (10 base)"; break;
bc97a989 544 case Exp: func = "Exponantial"; break;
72b7d4bc
LM
545 case Erfc: func = "Complementary Error Function"; break;
546 case Erf: func = "Error Function"; break;
9e52bbc5
LM
547 case Abs: func = "Absolute value"; break;
548 case Ceil: func = "Ceil value"; break;
549 case Floor: func = "Floor value"; break;
6ba1dd0f
LM
550 case Store: func = "Store"; break;
551 case Recall: func = "Recall"; break;
a8cf32ba
LM
552 case Inc: func = "Increase"; break;
553 case Dec: func = "Decrease"; break;
6ba1dd0f 554 case Disp: func = "Display"; break;
f438579a 555 case Mem: func = "Memory"; break;
143f91ae 556 case Clear: func = "Clear"; break;
471da7c9
LM
557 case Quit: func = "Quit"; break;
558 case Help: func = "Help"; break;
5075f6ea 559 case Ans: func = "Ans"; break;
471da7c9
LM
560 case Pi: func = "Pi"; break;
561 case E: func = "E"; break;
7fe742c9
LM
562 case Equal: func = "Equal"; break;
563 case Diff: func = "Different"; break;
564 case Ge: func = "Greater or equal"; break;
565 case Le: func = "Lesser or equal"; break;
566 case Gt: func = "Greater"; break;
567 case Lt: func = "Lesser"; break;
ca3e2a2f
LM
568 case And: func = "And"; break;
569 case Or: func = "Or"; break;
570 case Not: func = "Not"; break;
94b4e517 571 case Cond: func = "Condition"; break;
2a688642 572 case While: func = "While"; break;
05aabb97 573 case Code: func = "Code"; break;
715580ff 574 case Print: func = "Print"; break;
c7cbb833 575 case Prog: func = "Program"; break;
1e292005 576 case Arg: func = "Argument"; break;
c7cbb833
LM
577 case Call: func = "Call"; break;
578 case List: func = "List"; break;
579 case Edit: func = "Edit"; break;
580 case Del: func = "Del"; break;
a9a3da22
LM
581 case Get: func = "Get"; break;
582 case Length: func = "Length"; break;
583 case Pop: func = "Pop"; break;
584 case Push: func = "Push"; break;
585 case Put: func = "Put"; break;
586 case Set: func = "Set"; break;
587 case Show: func = "Show"; break;
226557a3
LM
588 case Max: func = "Maximum"; break;
589 case Mean: func = "Mean"; break;
590 case Median: func = "Median"; break;
591 case Min: func = "Minimum"; break;
592 case Order: func = "Order"; break;
593 case Prod: func = "Product"; break;
594 case Sum: func = "Sum"; break;
595 case Variance: func = "Variance"; break;
bc97a989
LM
596 }
597
04d68907 598 fprintf (stdout, "Function: %s\n", func);
bc97a989 599
85b4a72c 600 if ((root->func == Val) && (root->ops[0] == NULL)) {
bc97a989 601 for (i = 0; i < level; i++) {
04d68907 602 fprintf (stdout, " ");
bc97a989 603 }
04d68907 604 fprintf (stdout, "value: %f\n", root->value);
bc97a989
LM
605 } else {
606 for (i = 0; i < root->nbops; i++) {
607 print_element (root->ops[i], level + 1);
608 }
609 }
610}
611
6ba1dd0f
LM
612/* storage functions */
613
f438579a
LM
614void memory (int nb)
615{
616 int i, l;
617 double *tmp = NULL;
618 if (nb != storage_size) {
619 l = (nb < storage_size) ? nb : storage_size;
6f14d1cc 620 tmp = (double *) callocordie (nb, sizeof (double));
f438579a
LM
621 for (i = 0; i < l; i++) {
622 tmp[i] = storage[i];
623 }
624 if (storage != NULL) {
625 free (storage);
626 }
627 storage = tmp;
628 storage_size = nb;
629 }
630}
631
3639df66 632double store (int index, double value)
6ba1dd0f 633{
f438579a
LM
634 if (storage_size == -1) {
635 memory (DEFAULT_STORAGE_SIZE);
636 }
637 if ((index > 0) && (index <= storage_size)) {
3639df66 638 storage[index - 1] = value;
6ba1dd0f 639 } else {
9b759869 640 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
6ba1dd0f 641 }
3639df66 642 return value;
6ba1dd0f
LM
643}
644
645double recall (int index)
646{
f438579a
LM
647 if (storage_size == -1) {
648 memory (DEFAULT_STORAGE_SIZE);
649 }
650 if ((index > 0) && (index <= storage_size)) {
6ba1dd0f
LM
651 return storage[index - 1];
652 } else {
9b759869 653 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
6ba1dd0f
LM
654 }
655 return 0;
656}
657
a8cf32ba
LM
658double increase (int index)
659{
f438579a
LM
660 if (storage_size == -1) {
661 memory (DEFAULT_STORAGE_SIZE);
662 }
663 if ((index > 0) && (index <= storage_size)) {
a8cf32ba
LM
664 return storage[index - 1]++;
665 } else {
9b759869 666 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
a8cf32ba
LM
667 }
668 return 0;
669}
670
671double decrease (int index)
672{
f438579a
LM
673 if (storage_size == -1) {
674 memory (DEFAULT_STORAGE_SIZE);
675 }
676 if ((index > 0) && (index <= storage_size)) {
a8cf32ba
LM
677 return storage[index - 1]--;
678 } else {
9b759869 679 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size));
a8cf32ba
LM
680 }
681 return 0;
682}
683
6ba1dd0f
LM
684void display (void)
685{
686 int i;
f438579a
LM
687 if (storage_size == -1) {
688 memory (DEFAULT_STORAGE_SIZE);
689 }
6ba1dd0f 690 fprintf (stdout, "storage:");
f438579a 691 for (i = 0; i < storage_size; i++) {
9b759869
LM
692 fprintf (stdout, " ");
693 fprintf (stdout, minform, storage[i]);
6ba1dd0f
LM
694 }
695 fprintf (stdout, "\n");
696}
697
143f91ae
LM
698void clear ()
699{
700 int i;
701 for (i = 0; i < storage_size; i++) {
702 storage[i] = 0;
703 }
704}
705
2a688642
LM
706/* While do function */
707
708double while_do (element_t *cond, element_t *action)
709{
710 double ret = 0;
711 element_t *temp = NULL;
712
713 VERBOSE (DEBUG, fprintf (stdout, "starting while loop\n"));
2a688642
LM
714 while (1) {
715 VERBOSE (DEBUG, fprintf (stdout, "loop...\n"));
716
717 temp = dupelement (cond);
523841a1
ML
718 double test = evaluate_element (temp, 0);
719 delelement (temp);
720 if (!test) {
2a688642
LM
721 break;
722 }
723 if (action) {
724 temp = dupelement (action);
725 ret = evaluate_element (temp, 0);
523841a1 726 delelement (temp);
2a688642
LM
727 }
728 }
729
730 VERBOSE (DEBUG, fprintf (stdout, "ending while loop\n"));
731
732 return ret;
733}
734
124da7fd
LM
735/* program function */
736
05aabb97 737double execute_code (element_t **prog, int nbcalls)
124da7fd
LM
738{
739 double ret = 0;
740 int i;
741 for (i = 0; i < nbcalls; i++) {
742 ret = evaluate_element (prog[i], 0);
124da7fd
LM
743 }
744 return ret;
745}
746
2a5ec9d1
LM
747/* print function */
748
749void set_format (char *prompt, int precision)
750{
751 char buffer[128] = {0};
2a5ec9d1 752 free_format ();
9b759869 753 sprintf (buffer, "%s%%.%dg\n", prompt, precision);
2a5ec9d1 754 format = strdup (buffer);
9b759869
LM
755 sprintf (buffer, "%%.%dg", precision);
756 minform = strdup (buffer);
2a5ec9d1
LM
757}
758
759void free_format ()
760{
761 if (format) {
762 free (format);
763 format = NULL;
764 }
9b759869
LM
765 if (minform) {
766 free (minform);
767 minform = NULL;
768 }
2a5ec9d1
LM
769}
770
771double print (double value)
772{
f438579a 773 fprintf (stdout, format ? format : DEFAULT_FORMAT, value);
2a5ec9d1
LM
774 fflush (stdout);
775 return value;
776}
777
89cf0955
LM
778/* quit function */
779
780void quit (void)
781{
04d68907 782 fprintf (stdout, "bye\n");
89cf0955
LM
783 exit (0);
784}
785
c7cbb833
LM
786/* program function */
787
1e292005 788void prog (int id, element_t *root)
05aabb97
LM
789{
790 int i, n = -1;
791
792 if (programs == NULL) {
793
794 /* initial memory allocation */
6f14d1cc 795 programs = (workspace_t *) callocordie (1, sizeof (workspace_t));
05aabb97
LM
796 nb_programs = 1;
797 n = 0;
798
799 } else {
800
801 /* look for existing program */
802 for (i = 0; i < nb_programs; i++) {
803 if ((programs + i)->id == id) {
804 n = i;
805 break;
806 }
807 }
808 if (n == -1) {
809
810 /* new program */
811 n = nb_programs++;
6f14d1cc
LM
812 workspace_t *tmp = (workspace_t *) callocordie (nb_programs, sizeof (workspace_t));
813 memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t));
814 free (programs);
815 programs = tmp;
05aabb97
LM
816 } else {
817
818 /* clean old program */
819 if ((programs + n)->storage) {
820 free ((programs + n)->storage);
821 }
a9a3da22
LM
822 if ((programs + n)->stack) {
823 free ((programs + n)->stack);
824 }
05aabb97
LM
825 if ((programs + n)->root) {
826 delelement ((programs + n)->root);
827 }
2e34899a
LM
828 if ((programs + n)->string) {
829 free ((programs + n)->string);
0a8a1de3 830 (programs + n)->string = NULL;
2e34899a 831 }
05aabb97
LM
832 }
833 }
834
835 /* set program */
836 (programs + n)->id = id;
837 (programs + n)->answer = 0;
1e292005
LM
838 (programs + n)->storage = NULL;
839 (programs + n)->storage_size = 0;
a9a3da22
LM
840 (programs + n)->stack = NULL;
841 (programs + n)->stack_size = 0;
e7d5c144 842 (programs + n)->root = dupelement (root);
05aabb97 843}
c7cbb833 844
1e292005
LM
845double arg (int id)
846{
847 double ret = 0;
848 if ((id <= 0) || (id > argument_size)) {
849 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size));
850 } else {
851 ret = argument[id - 1];
852 }
853 return ret;
854}
855
856double call (int id, int nbargs, element_t **args)
c7cbb833 857{
05aabb97 858 workspace_t tmp = {0};
1e292005 859 int i, l, n = -1;
05aabb97
LM
860 double ret = 0;
861
862 if (programs) {
e7d5c144
LM
863
864 /* look for program */
05aabb97 865 for (i = 0; i < nb_programs; i++) {
e7d5c144 866 if ((programs + i)->id == id) {
05aabb97
LM
867 n = i;
868 break;
869 }
870 }
d59a8079
LM
871 }
872 if (n == -1) {
873 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
874 return 0;
875 }
05aabb97 876
d59a8079
LM
877 /* store context */
878 tmp.answer = answer;
1e292005
LM
879 tmp.argument = argument;
880 tmp.argument_size = argument_size;
d59a8079
LM
881 tmp.storage = storage;
882 tmp.storage_size = storage_size;
a9a3da22
LM
883 tmp.stack = stack;
884 tmp.stack_size = stack_size;
05aabb97 885
d59a8079
LM
886 /* change context */
887 answer = 0;
888 storage = (programs + n)->storage;
889 storage_size = (programs + n)->storage_size;
1e292005
LM
890 argument = NULL;
891 argument_size = 0;
a9a3da22
LM
892 stack = (programs + n)->stack;
893 stack_size = (programs + n)->stack_size;
1e292005
LM
894 if (nbargs > 0) {
895 argument = (double *) callocordie (nbargs, sizeof (double));
896 for (i = 0, l = 0; i < nbargs; l++) {
897 if (args[l]) {
898 argument[i++] = evaluate_element (args[l], 0);
899 }
900 }
901 argument_size = nbargs;
d59a8079
LM
902 }
903
904 /* evaluate program */
905 element_t *elements = dupelement ((programs + n)->root);
906 ret = evaluate_element (elements, 0);
523841a1 907 delelement (elements);
4747e9a1
LM
908 (programs + n)->answer = answer;
909 (programs + n)->storage = storage;
910 (programs + n)->storage_size = storage_size;
1e292005
LM
911 if (argument) {
912 free (argument);
913 }
4747e9a1
LM
914 (programs + n)->stack = stack;
915 (programs + n)->stack_size = stack_size;
d59a8079
LM
916
917 /* restore context */
918 answer = tmp.answer;
919 storage = tmp.storage;
4747e9a1 920 storage_size = tmp.storage_size;
1e292005
LM
921 argument = tmp.argument;
922 argument_size = tmp.argument_size;
4747e9a1 923 stack = tmp.stack;
a9a3da22 924 stack_size = tmp.stack_size;
05aabb97
LM
925
926 return ret;
c7cbb833
LM
927}
928
929void list ()
05aabb97
LM
930{
931 int i;
d59a8079
LM
932 fprintf (stdout, "programs:");
933 for (i = 0; i < nb_programs; i++) {
934 fprintf (stdout, " %d", (programs + i)->id);
05aabb97 935 }
d59a8079 936 fprintf (stdout, "\n");
05aabb97 937}
c7cbb833
LM
938
939void edit (int id)
2e34899a
LM
940{
941 int i, n = -1;
942
943 if (programs) {
944
945 /* look for program */
946 for (i = 0; i < nb_programs; i++) {
947 if ((programs + i)->id == id) {
948 n = i;
949 break;
950 }
951 }
952 }
953 if (n == -1) {
954 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
955 return;
956 }
957
958 /* set string program */
779282bb 959 fprintf (stdout, "edit: %s\n", (programs + n)->string);
2e34899a
LM
960}
961
779282bb 962void savestring (int id, char *string)
2e34899a
LM
963{
964 int i, n = -1;
965
966 if (programs) {
967
968 /* look for program */
969 for (i = 0; i < nb_programs; i++) {
970 if ((programs + i)->id == id) {
971 n = i;
972 break;
973 }
974 }
975 }
2e34899a 976
1b068216
LM
977 /* unnecesary code */
978 //if (n == -1) {
979 // VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
980 // return;
981 //}
982 //if ((programs + n)->string) {
983 // free ((programs + n)->string);
984 //}
985
226557a3
LM
986 if (string) {
987 (programs + n)->string = strdup (string);
988 }
2e34899a 989}
c7cbb833
LM
990
991void del (int id)
d59a8079
LM
992{
993 int i, j, n = -1;
994
995 if (programs) {
996
997 /* look for program */
998 for (i = 0; i < nb_programs; i++) {
999 if ((programs + i)->id == id) {
1000 n = i;
1001 break;
1002 }
1003 }
1004 }
1005 if (n == -1) {
1006 VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id));
1007 return;
1008 }
1009
1010 /* clean program */
1011 if ((programs + n)->storage) {
1012 free ((programs + n)->storage);
1013 }
a9a3da22
LM
1014 if ((programs + n)->stack) {
1015 free ((programs + n)->stack);
1016 }
d59a8079
LM
1017 if ((programs + n)->root) {
1018 delelement ((programs + n)->root);
1019 }
2e34899a
LM
1020 if ((programs + n)->string) {
1021 free ((programs + n)->string);
1022 }
d59a8079
LM
1023
1024 /* remove entry */
1025 workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t));
1026 for (i = 0, j = 0; i < nb_programs; i++) {
1027 if (i != n) {
1028 memcpy (tmp + j, programs + i, sizeof (workspace_t));
1029 j++;
1030 }
1031 }
1032 free (programs);
1033 programs = tmp;
1034 nb_programs--;
1035}
c7cbb833 1036
a9a3da22
LM
1037/* stack management */
1038
1039double get (int n)
1040{
1041 double ret = 0;
1042 if ((n <= 0) || (n > stack_size)) {
1043 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size));
1044 } else {
1045 ret = stack[n - 1];
1046 }
1047 return ret;
1048}
1049
1050double length ()
1051{
1052 return stack_size;
1053}
1054
1055double pop ()
1056{
1057 double ret = 0;
1058 if (stack_size > 0) {
1059 ret = stack[--stack_size];
1060 double *tmp = (double *) callocordie (stack_size, sizeof (double));
1061 memcpy (tmp, stack, stack_size * sizeof (double));
1062 free (stack);
1063 stack = tmp;
1064 } else {
1065 VERBOSE (WARNING, fprintf (stdout, "error stack empty\n"));
1066 }
1067 return ret;
1068}
1069
1070double push (double val)
1071{
1072 double *tmp = (double *) callocordie (stack_size + 1, sizeof (double));
1073 memcpy (tmp, stack, stack_size * sizeof (double));
1074 if (stack) {
1075 free (stack);
1076 }
1077 stack = tmp;
1078 stack[stack_size++] = val;
1079 return val;
1080}
1081
1082double put (int n, double val)
1083{
1084 if (n <= 0) {
1085 VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size));
1086 return 0;
1087 }
1088 if (n > stack_size) {
1089 double *tmp = (double *) callocordie (n, sizeof (double));
1090 memcpy (tmp, stack, stack_size * sizeof (double));
1091 free (stack);
1092 stack = tmp;
1093 stack_size = n;
1094 }
1095 stack[n - 1] = val;
1096 return val;
1097}
1098
1099double set (int nbops, element_t **ops)
1100{
1101 int i;
1102 if (stack) {
1103 free (stack);
1104 }
1105 stack = NULL;
1106 stack_size = 0;
1107 if (nbops != 0) {
1108 stack = (double *) callocordie (nbops, sizeof (double));
1109 for (i = 0; i < nbops; i++) {
1110 stack[i] = evaluate_element (ops[i], 0);
1111 }
1112 stack_size = nbops;
1113 }
1114 return stack_size;
1115}
1116
1117void show (void)
1118{
1119 int i;
1120 fprintf (stdout, "stack:");
1121 for (i = 0; i < stack_size; i++) {
1122 fprintf (stdout, " ");
1123 fprintf (stdout, minform, stack[i]);
1124 }
1125 fprintf (stdout, "\n");
1126}
1127
226557a3
LM
1128/* stack functions */
1129
1130double max ()
1131{
1132 double ret = 0;
1133 int i;
1134 if (stack_size < 1) {
1135 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1136 return 0;
1137 }
1138 ret = stack[0];
1139 for (i = 1; i < stack_size; i++) {
1140 if (stack[i] > ret) {
1141 ret = stack[i];
1142 }
1143 }
1144 return ret;
1145}
1146
1147double mean ()
1148{
1149 double ret = 0;
1150 int i;
1151 if (stack_size < 1) {
1152 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1153 return 0;
1154 }
1155 for (i = 0; i < stack_size; i++) {
1156 ret += stack[i];
1157 }
1158 return ret / stack_size;
1159}
1160
1161double min ()
1162{
1163 double ret = 0;
1164 int i;
1165 if (stack_size < 1) {
1166 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1167 return 0;
1168 }
1169 ret = stack[0];
1170 for (i = 1; i < stack_size; i++) {
1171 if (stack[i] < ret) {
1172 ret = stack[i];
1173 }
1174 }
1175 return ret;
1176}
1177
1178void order ()
1179{
1180 int i, j;
1181 if (stack_size < 1) {
1182 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1183 return;
1184 }
1185 for (i = 0; i < stack_size - 1; i++) {
1186 int done = 0;
1187 for (j = 0; j < stack_size - 1; j++) {
1188 if (stack[j] > stack[j + 1]) {
1189 double tmp = stack[j];
1190 stack[j] = stack[j + 1];
1191 stack[j + 1] = tmp;
1192 done = 1;
1193 }
1194 }
1195 if (done == 0) {
1196 break;
1197 }
1198 }
1199}
1200
1201double median ()
1202{
1203 double ret = 0;
1204 if (stack_size < 3) {
1205 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1206 return 0;
1207 }
1208 double *tmp = (double *) callocordie (stack_size, sizeof (double));
1209 memcpy (tmp, stack, stack_size * sizeof (double));
1210 order ();
1211 ret = stack[(stack_size - 1)/ 2];
1212 memcpy (stack, tmp, stack_size * sizeof (double));
1213 free (tmp);
1214 return ret;
1215}
1216
1217double prod ()
1218{
1219 double ret = 1;
1220 int i;
1221 if (stack_size < 1) {
1222 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1223 return 0;
1224 }
1225 for (i = 0; i < stack_size; i++) {
1226 ret *= stack[i];
1227 }
1228 return ret;
1229}
1230
1231double sum ()
1232{
1233 double ret = 0;
1234 int i;
1235 if (stack_size < 1) {
1236 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1237 return 0;
1238 }
1239 for (i = 0; i < stack_size; i++) {
1240 ret += stack[i];
1241 }
1242 return ret;
1243}
1244
1245double variance ()
1246{
1247 double ret = 0;
1248 double m = 0;
1249 int i;
1250 if (stack_size < 2) {
1251 VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size));
1252 return 0;
1253 }
1254 m = mean ();
1255 for (i = 0; i < stack_size; i++) {
1256 ret += (stack[i] - m) * (stack[i] - m);
1257 }
1258 return ret / stack_size;
1259}
1260
1261
89cf0955
LM
1262/* help message */
1263
1264void help (void)
1265{
04d68907 1266 fprintf (stdout, "calc is a simple calculator\n\n");
0e1004e3 1267 fprintf (stdout, "arithmetic op.:");
94b4e517 1268 fprintf (stdout, " + - * / %% ^\n");
0e1004e3 1269 fprintf (stdout, "comparison op.:");
94b4e517 1270 fprintf (stdout, " == != >= <= > <\n");
0e1004e3 1271 fprintf (stdout, "logical op.:");
94b4e517 1272 fprintf (stdout, " & | !\n");
0e1004e3 1273 fprintf (stdout, "mathematic func.:");
347b66f8 1274 fprintf (stdout, " exp ln log pow sqrt\n");
0e1004e3 1275 fprintf (stdout, "trigonometric func.:");
347b66f8 1276 fprintf (stdout, " acos asin atan cos sin tan\n");
72b7d4bc
LM
1277 fprintf (stdout, "error functions:");
1278 fprintf (stdout, " erf erfc\n");
0e1004e3 1279 fprintf (stdout, "miscellaneous func.:");
9e52bbc5 1280 fprintf (stdout, " abs ceil floor\n");
0e1004e3 1281 fprintf (stdout, "storage func.:");
347b66f8 1282 fprintf (stdout, " clear dec disp inc mem rcl sto\n");
0e1004e3 1283 fprintf (stdout, "control flow prim.:");
347b66f8 1284 fprintf (stdout, " cond print while {} ;\n");
0e1004e3 1285 fprintf (stdout, "program management:");
1e292005 1286 fprintf (stdout, " arg call del edit ls prog\n");
a9a3da22
LM
1287 fprintf (stdout, "stack management:");
1288 fprintf (stdout, " get len pop push put set show\n");
226557a3
LM
1289 fprintf (stdout, "stack func.:");
1290 fprintf (stdout, " max mean med min ord prod sum var\n");
0e1004e3 1291 fprintf (stdout, "control management:");
347b66f8 1292 fprintf (stdout, " help quit\n");
0e1004e3 1293 fprintf (stdout, "constants:");
347b66f8 1294 fprintf (stdout, " ans e pi\n");
89cf0955 1295}
3b4b0bbe 1296
f2927108
LM
1297/* evaluate element tree */
1298
89cf0955
LM
1299#define MASK_SUB 0x1
1300#define MASK_DIV 0x2
1301
3b4b0bbe 1302double evaluate_element (element_t *root, char mask)
f2927108
LM
1303{
1304 double op0 = 0, op1 = 0;
3b4b0bbe 1305 char nextmask = mask;
e7d5c144 1306 int i, nb;
f2927108
LM
1307
1308 if ((root == NULL) || (root == ERROR_OP)) {
04d68907 1309 VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n"));
f2927108
LM
1310 return 0;
1311 }
1312
3b4b0bbe
LM
1313 /* mask to manage sub operator sub and div */
1314 switch (root->func) {
1315 case Add:
1316 nextmask &= ~MASK_SUB;
1317 nextmask &= ~MASK_DIV;
1318 break;
1319 case Sub:
1320 nextmask |= MASK_SUB;
1321 nextmask &= ~MASK_DIV;
1322 break;
1323 case Mul:
1324 nextmask &= ~MASK_DIV;
1325 break;
1326 case Div:
1327 nextmask |= MASK_DIV;
1328 break;
1329 default:
1330 nextmask = mask;
1331 }
1332
f2927108
LM
1333 switch (root->func) {
1334 case Val:
3b4b0bbe
LM
1335 case Sig:
1336 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
f2927108
LM
1337 break;
1338 case Add:
1339 case Sub:
1340 case Mul:
1341 case Div:
c47a9298 1342 case Mod:
f2927108 1343 case Pow:
3639df66 1344 case Store:
7fe742c9
LM
1345 case Equal:
1346 case Diff:
1347 case Ge:
1348 case Le:
1349 case Gt:
1350 case Lt:
ca3e2a2f
LM
1351 case And:
1352 case Or:
f2927108 1353 if (root->ops[1]) {
3b4b0bbe 1354 op1 = evaluate_element (root->ops[1], nextmask);
3639df66 1355 } else if (root->func != Store) {
04d68907 1356 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
f2927108
LM
1357 return 0;
1358 }
1359 /* fallthrough */
1360 case Sqr:
1361 case Cos:
1362 case Sin:
9e52bbc5
LM
1363 case Tan:
1364 case Acos:
1365 case Asin:
471da7c9 1366 case Atan:
2a986c8f 1367 case Ln:
f2927108
LM
1368 case Log:
1369 case Exp:
72b7d4bc
LM
1370 case Erfc:
1371 case Erf:
9e52bbc5
LM
1372 case Abs:
1373 case Ceil:
1374 case Floor:
6ba1dd0f 1375 case Recall:
a8cf32ba
LM
1376 case Inc:
1377 case Dec:
ca3e2a2f 1378 case Not:
f438579a 1379 case Mem:
94b4e517 1380 case Cond:
1e292005
LM
1381 case Prog:
1382 case Arg:
c7cbb833 1383 case Call:
c7cbb833
LM
1384 case Edit:
1385 case Del:
a9a3da22 1386 case Get:
f2927108 1387 if (root->ops[0]) {
3b4b0bbe 1388 op0 = evaluate_element (root->ops[0], 0);
f2927108 1389 } else {
04d68907 1390 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
f2927108
LM
1391 return 0;
1392 }
89cf0955 1393 break;
6ba1dd0f 1394 case Disp:
143f91ae 1395 case Clear:
471da7c9
LM
1396 case Quit:
1397 case Help:
5075f6ea 1398 case Ans:
471da7c9
LM
1399 case Pi:
1400 case E:
05aabb97 1401 case Code:
e7d5c144 1402 case List:
a9a3da22
LM
1403 case Length:
1404 case Pop:
1405 case Set:
1406 case Show:
226557a3
LM
1407 case Median:
1408 case Order:
1409 case Prod:
1410 case Sum:
09d87cae 1411 break;
2a688642 1412 case While:
09d87cae
LM
1413 if (root->ops[0] == NULL) {
1414 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1415 return 0;
1416 }
89cf0955 1417 break;
a9a3da22 1418 case Push:
715580ff
LM
1419 case Print:
1420 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
1421 break;
a9a3da22
LM
1422 case Put:
1423 if (root->ops[0]) {
1424 op0 = evaluate_element (root->ops[0], 0);
1425 } else {
1426 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
1427 return 0;
1428 }
1429 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
1430 break;
226557a3
LM
1431 case Max:
1432 case Mean:
1433 case Min:
1434 case Variance:
1435 if (root->ops[0]) {
1436 op0 = evaluate_element (root->ops[0], 0);
1437 op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer;
1438 }
f2927108
LM
1439 }
1440
1441 switch (root->func) {
3b4b0bbe
LM
1442 case Val: return op0;
1443 case Sig: return -op0;
1444 case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1;
1445 case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1;
1446 case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1;
1447 case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1;
c47a9298 1448 case Mod: return fmod (op0, op1);
f2927108
LM
1449 case Pow: return pow (op0, op1);
1450 case Sqr: return sqrt (op0);
1451 case Cos: return cos (op0);
1452 case Sin: return sin (op0);
9e52bbc5
LM
1453 case Tan: return tan (op0);
1454 case Acos: return acos (op0);
1455 case Asin: return asin (op0);
471da7c9 1456 case Atan: return atan (op0);
2a986c8f
LM
1457 case Ln: return log (op0);
1458 case Log: return log10 (op0);
f2927108 1459 case Exp: return exp (op0);
72b7d4bc
LM
1460 case Erfc: return erfc (op0);
1461 case Erf: return erf (op0);
9e52bbc5
LM
1462 case Abs: return fabs (op0);
1463 case Ceil: return ceil (op0);
1464 case Floor: return floor (op0);
3639df66 1465 case Store: return store ((int)op0, (op1) ? op1 : answer);
6ba1dd0f 1466 case Recall: return recall ((int)op0);
a8cf32ba
LM
1467 case Inc: return increase ((int)op0);
1468 case Dec: return decrease ((int)op0);
6ba1dd0f 1469 case Disp: display (); break;
f438579a 1470 case Mem: memory ((int)op0); break;
143f91ae 1471 case Clear: clear (); break;
471da7c9
LM
1472 case Quit: quit (); break;
1473 case Help: help (); break;
5075f6ea 1474 case Ans: return answer;
471da7c9
LM
1475 case Pi: return M_PI;
1476 case E: return M_E;
7fe742c9
LM
1477 case Equal: return op0 == op1;
1478 case Diff: return op0 != op1;
1479 case Ge: return op0 >= op1;
1480 case Le: return op0 <= op1;
1481 case Gt: return op0 > op1;
1482 case Lt: return op0 < op1;
ca3e2a2f
LM
1483 case And: return (op0 != 0) && (op1 != 0);
1484 case Or: return (op0 != 0) || (op1 != 0);
1485 case Not: return (op0 == 0);
94b4e517
LM
1486 case Cond:
1487 if ((op0) && (root->ops[1])) {
1488 return evaluate_element (root->ops[1], 0);
1489 } else if ((!op0) && (root->ops[2])) {
1490 return evaluate_element (root->ops[2], 0);
1491 } else {
1492 return 0;
1493 }
2a688642 1494 case While: return while_do (root->ops[0], root->ops[1]);
05aabb97 1495 case Code: return execute_code (root->ops, root->nbops);
2a5ec9d1 1496 case Print: return print (op0);
779282bb 1497 case Prog:
1e292005 1498 prog ((int)op0, root->ops[1]);
779282bb
LM
1499 savestring ((int)op0, root->string);
1500 break;
1e292005 1501 case Arg: return arg ((int)op0);
e7d5c144
LM
1502 case Call:
1503 for (i = 1, nb =0; i < root->nbops; i++) {
1504 if (root->ops[i]) {
1505 nb++;
1506 }
1507 }
1508 return call ((int)op0, nb, root->ops + 1);
c7cbb833
LM
1509 case List: list (); break;
1510 case Edit: edit ((int)op0); break;
05aabb97 1511 case Del: del ((int)op0); break;
a9a3da22
LM
1512 case Get: return get ((int)op0);
1513 case Length: return length ();
1514 case Pop: return pop ();
1515 case Push: return push (op0);
1516 case Put: return put ((int)op0, op1);
1517 case Set:
1518 for (i = 0, nb =0; i < root->nbops; i++) {
1519 if (root->ops[i]) {
1520 nb++;
1521 }
1522 }
1523 return set (nb, root->ops);
1524 case Show: show (); break;
226557a3
LM
1525 case Max:
1526 if (root->ops[0]) {
1527 return op0 > op1 ? op0 : op1;
1528 }
1529 return max ();
1530 case Mean:
1531 if (root->ops[0]) {
1532 return (op0 + op1) / 2;
1533 }
1534 return mean ();
1535 case Median: return median ();
1536 case Min:
1537 if (root->ops[0]) {
1538 return op0 < op1 ? op0 : op1;
1539 }
1540 return min ();
1541 case Order: order (); break;
1542 case Prod: return prod ();
1543 case Sum: return sum ();
1544 case Variance:
1545 if (root->ops[0]) {
1546 double m = (op0 + op1) / 2;
1547 op0 -= m;
1548 op1 -= m;
1549 return op0 * op0 + op1 * op1;
1550 }
1551 return variance ();
f2927108
LM
1552 }
1553
1554 return 0;
1555}
1556
b9c1c40d
LM
1557char **generate_completion_list ()
1558{
db660e60 1559 int i, j, l = 0;
6f14d1cc 1560 char **list = (char **) callocordie (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *));
b9c1c40d 1561
db660e60
LM
1562 for (i = 0; i < NB_OPERATORS; i++) {
1563 list[l] = strdup ((operators + i)->keyword);
1564 for (j = 0; j < (int)strlen (list[l]); j++) {
1565 if (list[i][j] == '\t') {
1566 list[i][j] = '\0';
1567 }
1568 }
d8f4df0f
LM
1569 if (list[l] != NULL) {
1570 l++;
db660e60 1571 }
db660e60
LM
1572 }
1573
b9c1c40d
LM
1574 for (i = 0; i < NB_FUNCTIONS; i++) {
1575 list[l] = strdup ((functions + i)->keyword);
d8f4df0f
LM
1576 if (list[l] != NULL) {
1577 l++;
b9c1c40d 1578 }
b9c1c40d
LM
1579 }
1580
1581 for (i = 0; i < NB_CONSTANTS; i++) {
1582 list[l] = strdup ((constants + i)->keyword);
d8f4df0f
LM
1583 if (list[l] != NULL) {
1584 l++;
b9c1c40d 1585 }
b9c1c40d
LM
1586 }
1587
db660e60
LM
1588 for (i = 0; i < NB_SYMBOLS; i++) {
1589 list[l] = strdup (symbols[i]);
d8f4df0f
LM
1590 if (list[l] != NULL) {
1591 l++;
db660e60 1592 }
db660e60
LM
1593 }
1594
b9c1c40d
LM
1595 return (list);
1596}
1597
1598void free_completion_list (char **list)
1599{
1600 int i;
1601
1602 if (list) {
3d3e6770 1603 for (i = 0; i < NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1; i++) {
b9c1c40d
LM
1604 if (list[i] != NULL) {
1605 free (list[i]);
1606 }
1607 }
1608 free (list);
1609 }
1610}
1611
1612
bc97a989 1613/* vim: set ts=4 sw=4 et: */