1 /*
2 * eval.c -- functions for builtin calculator
3 *
4 * (created: Massimiliano Ghilardi (Cosmos), Jan 15th, 1995)
5 *
6 * Copyright (C) 1998 by Massimiliano Ghilardi
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <time.h>
22 #include <sys/types.h>
23 #include <sys/time.h>
24 #include <limits.h>
25
26 #include "defines.h"
27 #include "main.h"
28 #include "utils.h"
29 #include "cmd2.h"
30 #include "list.h"
31 #include "map.h"
32 #include "tty.h"
33 #include "edit.h"
34 #include "eval.h"
35
36 #ifdef USE_RANDOM
37 # define get_random random
38 # define init_random srandom
39 #else
40 # define get_random lrand48
41 # define init_random srand48
42 #endif
43
44 typedef struct {
45 int type;
46 long num; /* used for numeric types or as index for all variables */
47 ptr txt; /* used for text types */
48 } object;
49
50 #define LEFT 1
51 #define RIGHT 2
52
53 #define BINARY 0
54 #define PRE_UNARY LEFT
55 #define POST_UNARY RIGHT
56
57 #define LOWEST_UNARY_CODE 49
58 /*
59 * it would be 47, but operators 47 '(' and 48 ')'
60 * are treated separately
61 */
62
63 enum op_codes {
64 null=0, comma, eq, or_or_eq, xor_xor_eq, and_and_eq, or_eq, xor_eq, and_eq,
65 lshift_eq, rshift_eq, plus_eq, minus_eq, times_eq, div_eq, ampersand_eq,
66 or_or, xor_xor, and_and, or, xor, and,
67 less, less_eq, greater, greater_eq, eq_eq, not_eq,
68 lshift, rshift, plus, minus, times, division, ampersand,
69
70 colon_less, colon_greater, less_colon, greater_colon,
71 point_less, point_greater, less_point, greater_point,
72 colon, point, question, another_null,
73
74 left_paren, right_paren, not, tilde,
75 pre_plus_plus, post_plus_plus, pre_minus_minus, post_minus_minus,
76 star, print, _random_, _attr_, colon_question, point_question,
77 pre_plus, pre_minus, a_circle, dollar, pre_null, post_null
78 };
79
80 typedef enum op_codes operator;
81
82 typedef struct {
83 char priority, assoc, syntax, *name;
84 operator code;
85 } operator_list;
86
87 typedef struct {
88 object obj[MAX_STACK];
89 int curr_obj;
90 operator op[MAX_STACK];
91 int curr_op;
92 } stack;
93
94 char *error_msg[] = {
95 "unknown error",
96 "math stack overflow",
97 "math stack underflow",
98 "stack overflow",
99 "stack underflow",
100 "expression syntax",
101 "operator expected",
102 "value expected",
103 "division by zero",
104 "operand or index out of range",
105 "missing right parenthesis",
106 "missing left parenthesis",
107 "internal error!",
108 "operator not supported",
109 "operation not completed (internal error)",
110 "out of memory",
111 "text/string longer than limit, discarded",
112 "infinite loop",
113 "numeric value expected",
114 "string expected",
115 "missing label",
116 "missing separator \";\"",
117 "#history recursion too deep",
118 "user break",
119 "too many defined variables",
120 "undefined variable",
121 "invalid digit in numeric value",
122 "bad attribute syntax",
123 "invalid variable name",
124 };
125
126 operator_list op_list[] = {
127 { 0, 0, 0, "", null },
128
129 { 1, LEFT, BINARY, ",", comma },
130
131 { 2, RIGHT, BINARY, "=", eq },
132 { 2, RIGHT, BINARY, "||=", or_or_eq },
133 { 2, RIGHT, BINARY, "^^=", xor_xor_eq },
134 { 2, RIGHT, BINARY, "&&=", and_and_eq },
135 { 2, RIGHT, BINARY, "|=", or_eq },
136 { 2, RIGHT, BINARY, "^=", xor_eq },
137 { 2, RIGHT, BINARY, "&=", and_eq },
138 { 2, RIGHT, BINARY, "<<=", lshift_eq },
139 { 2, RIGHT, BINARY, ">>=", rshift_eq },
140 { 2, RIGHT, BINARY, "+=", plus_eq },
141 { 2, RIGHT, BINARY, "-=", minus_eq },
142 { 2, RIGHT, BINARY, "*=", times_eq },
143 { 2, RIGHT, BINARY, "/=", div_eq },
144 { 2, RIGHT, BINARY, "%=", ampersand_eq },
145
146 { 3, LEFT, BINARY, "||", or_or },
147
148 { 4, LEFT, BINARY, "^^", xor_xor },
149
150 { 5, LEFT, BINARY, "&&", and_and },
151
152 { 6, LEFT, BINARY, "|", or },
153
154 { 7, LEFT, BINARY, "^", xor },
155
156 { 8, LEFT, BINARY, "&", and },
157
158 { 9, LEFT, BINARY, "<", less },
159 { 9, LEFT, BINARY, "<=", less_eq },
160 { 9, LEFT, BINARY, ">", greater },
161 { 9, LEFT, BINARY, ">=", greater_eq },
162 { 9, LEFT, BINARY, "==", eq_eq },
163 { 9, LEFT, BINARY, "!=", not_eq },
164
165 {10, LEFT, BINARY, "<<", lshift },
166 {10, LEFT, BINARY, ">>", rshift },
167
168 {11, LEFT, BINARY, "+", plus },
169 {11, LEFT, BINARY, "-", minus },
170
171 {12, LEFT, BINARY, "*", times },
172 {12, LEFT, BINARY, "/", division },
173 {12, LEFT, BINARY, "%", ampersand },
174
175 {14, LEFT, BINARY, ":<", colon_less },
176 {14, LEFT, BINARY, ":>", colon_greater },
177 {14, LEFT, BINARY, "<:", less_colon },
178 {14, LEFT, BINARY, ">:", greater_colon },
179 {14, LEFT, BINARY, ".<", point_less },
180 {14, LEFT, BINARY, ".>", point_greater },
181 {14, LEFT, BINARY, "<.", less_point },
182 {14, LEFT, BINARY, ">.", greater_point },
183 {14, LEFT, BINARY, ":", colon },
184 {14, LEFT, BINARY, ".", point },
185 {14, LEFT, BINARY, "?", question },
186
187 { 0, 0, 0, "", another_null },
188
189 { 0, RIGHT, PRE_UNARY, "(", left_paren },
190 { 0, RIGHT, POST_UNARY, ")", right_paren },
191
192 {13, RIGHT, PRE_UNARY, "!", not },
193 {13, RIGHT, PRE_UNARY, "~", tilde },
194 {13, RIGHT, PRE_UNARY, "++", pre_plus_plus },
195 {13, RIGHT, POST_UNARY, "++", post_plus_plus },
196 {13, RIGHT, PRE_UNARY, "--", pre_minus_minus },
197 {13, RIGHT, POST_UNARY, "--", post_minus_minus },
198 {13, RIGHT, PRE_UNARY, "*", star },
199 {13, RIGHT, PRE_UNARY, "%", print },
200 {13, RIGHT, PRE_UNARY, "rand", _random_ },
201 {13, RIGHT, PRE_UNARY, "attr", _attr_ },
202
203 {14, LEFT, PRE_UNARY, ":?", colon_question },
204 {14, LEFT, PRE_UNARY, ".?", point_question },
205
206 {15, RIGHT, PRE_UNARY, "+", pre_plus },
207 {15, RIGHT, PRE_UNARY, "-", pre_minus },
208 {15, RIGHT, PRE_UNARY, "@", a_circle },
209 {15, RIGHT, PRE_UNARY, "$", dollar },
210
211 { 0, 0, PRE_UNARY, "", pre_null },
212 { 0, 0, POST_UNARY, "", post_null }
213 };
214
215 static stack stk;
216 static char *line;
217 static int depth;
218 int error;
219
__P1(int,err_num)220 void print_error __P1 (int,err_num)
221 {
222 clear_input_line(1);
223 if (error == NO_MEM_ERROR) {
224 tty_printf("#system call error: %s (%d", "malloc", ENOMEM);
225 tty_printf(": %s)\n", strerror(ENOMEM));
226 } else
227 tty_printf("#error: %s.\n", error_msg[err_num]);
228 }
229
__P1(operator *,op)230 static int push_op __P1 (operator *,op)
231 {
232 if (stk.curr_op<MAX_STACK) {
233 stk.op[++stk.curr_op]=*op;
234 return 1;
235 }
236 else {
237 error=STACK_OV_ERROR;
238 return 0;
239 }
240 }
241
__P1(operator *,op)242 static int pop_op __P1 (operator *,op)
243 {
244 if (stk.curr_op>=0) {
245 *op=stk.op[stk.curr_op--];
246 return 1;
247 }
248 else {
249 error=STACK_UND_ERROR;
250 return 0;
251 }
252 }
253
__P1(object *,obj)254 static int push_obj __P1 (object *,obj)
255 {
256 object *tmp;
257
258 int curr=stk.curr_obj;
259
260 if (curr<MAX_STACK) {
261 tmp = stk.obj + (stk.curr_obj = ++curr);
262 memmove(tmp, obj, sizeof(object));
263 return 1;
264 }
265 else {
266 error=STACK_OV_ERROR;
267 return 0;
268 }
269 }
270
__P1(object *,obj)271 static int pop_obj __P1 (object *,obj)
272 {
273 object *tmp;
274
275 int curr=stk.curr_obj;
276
277 if (curr>=0) {
278 tmp = stk.obj + curr;
279 stk.curr_obj--;
280 memmove(obj, tmp, sizeof(object));
281 return 1;
282 }
283 else {
284 error=STACK_UND_ERROR;
285 return 0;
286 }
287 }
288
__P3(char,side,operator *,op,int,mindepth)289 static int check_operator __P3 (char,side, operator *,op, int,mindepth)
290 {
291 int i, max, len;
292 operator match;
293 char *name, c, d;
294
295 if (!(c=*line) || c == CMDSEP) {
296 *op = side==BINARY ? null : side==LEFT ? pre_null : post_null;
297 return 1;
298 }
299 else if ((c=='$' || c=='@') && (d=line[1]) && (isalpha(d) || d=='_'))
300 return 0; /* Danger! found named variable */
301
302 else if (side==LEFT && c=='(') {
303 line++;
304 depth++;
305 *op=left_paren;
306 return 1;
307 }
308 else if (side==RIGHT && c==')') {
309 if (--depth >= mindepth) {
310 line++;
311 *op=right_paren;
312 }
313 else /* exit without touching the parenthesis */
314 *op=post_null;
315 return 1;
316 }
317 else if (side==RIGHT && (c=='}' || c==']') && depth == mindepth) {
318 /* allow also exiting with a '}' or a ']' */
319 --depth;
320 *op=post_null;
321 return 1;
322 }
323
324 for (max=match=0, i=(side==BINARY ? 1 : LOWEST_UNARY_CODE);
325 *(name = op_list[i].name); i++)
326 if ((len=strlen(name)) > max &&
327 (side==BINARY || side==op_list[i].syntax) &&
328 !strncmp(line, name, (size_t)len)) {
329 match=op_list[i].code;
330 max=len;
331 }
332
333 if (match) {
334 *op=match;
335 line+=max;
336 return 1;
337 }
338 else {
339 *op= side==BINARY ? null : side==PRE_UNARY ? pre_null : post_null;
340 if (side==BINARY)
341 error=NO_OPERATOR_ERROR;
342 }
343 return 0;
344 }
345
__P1(object *,obj)346 static int check_object __P1 (object *,obj)
347 {
348 long i=0, base = 10;
349 char c, *end, digit;
350
351 if (c=*line, c == '#' || isdigit(c)) {
352 while (c == '#' || isalnum(c)) {
353 digit = !!isdigit(c);
354 if (c == '#') {
355 base = i;
356 i = 0;
357 if (!base)
358 base = 16;
359 } else {
360 i *= base;
361 if (digit)
362 i += (c - '0');
363 else {
364 if (c >= 'a' && c <= 'z')
365 c = (c - 'a') + 'A';
366 if (c - 'A' + 10 >= base) {
367 error=OUT_BASE_ERROR;
368 return 0;
369 }
370 i += (c - 'A' + 10);
371 }
372 }
373 c=*++line;
374 }
375 obj->type=TYPE_NUM;
376 obj->num=i;
377 i=1;
378 }
379 else if(c=='\"') {
380 end=first_valid(++line, '\"');
381 if (*end) {
382 obj->type=TYPE_TXT;
383 obj->txt=ptrmcpy(obj->txt, line, end-line);
384 if (!REAL_ERROR) {
385 ptrunescape(obj->txt);
386 i=1;
387 line=end+1;
388 }
389 }
390 }
391 else if ((c=='$' || c=='@') && (c=line[1]) && (isalpha(c) || c=='_')) {
392 varnode *named_var; /* Found named variable */
393
394 if (*(line++) == '@') {
395 i = 0;
396 obj->type = TYPE_NUM_VAR;
397 }
398 else {
399 i = 1;
400 obj->type = TYPE_TXT_VAR;
401 }
402 end = line + 1;
403 while ((c=*end) && (isalpha(c) || c=='_' || isdigit(c)))
404 end++;
405 c = *end; *end = '\0';
406 if (!(named_var = *lookup_varnode(line, i))) {
407 named_var = add_varnode(line, i);
408 if (REAL_ERROR)
409 return 0;
410 if (opt_info) {
411 PRINTF("#new variable: %s\n", line - 1);
412 }
413 }
414 *end = c;
415 line = end;
416 obj->num = named_var->index;
417 i = 1;
418 }
419 else if (!strncmp(line, "timer", 5)) {
420 obj->type = TYPE_NUM;
421 update_now();
422 obj->num = diff_vtime(&now, &ref_time);
423 line += 5;
424 i = 1;
425 }
426 else if (!strncmp(line, "map", 3)) {
427 char buf[MAX_MAPLEN + 1];
428 map_sprintf(buf);
429 obj->type = TYPE_TXT;
430 obj->txt = ptrmcpy(obj->txt, buf, strlen(buf));
431 if (!REAL_ERROR) {
432 line += 3;
433 i = 1;
434 }
435 }
436 else if (!strncmp(line, "noattr", 6)) {
437 obj->type = TYPE_TXT;
438 obj->txt = ptrmcpy(obj->txt, tty_modestandoff, strlen(tty_modestandoff));
439 obj->txt = ptrmcat(obj->txt, tty_modenorm, strlen(tty_modenorm));
440 if (!REAL_ERROR) {
441 line += 6;
442 i = 1;
443 }
444 }
445 else
446 error=NO_VALUE_ERROR;
447
448 return (int)i;
449 }
450
__P1(object *,obj)451 static void check_delete __P1 (object *,obj)
452 {
453 if (obj->type==TYPE_TXT && obj->txt) {
454 ptrdel(obj->txt);
455 obj->txt = NULL;
456 }
457 }
458
__P1(operator *,op)459 static int exe_op __P1 (operator *,op)
460 {
461 object o1, o2, *p=NULL;
462 long *l, rnd, delta;
463 ptr src = NULL, dst = NULL, start = NULL;
464 int srclen;
465 char *ssrc, *tmp;
466 int ret=0, i=0, j=0, danger=0;
467
468 o1.txt = o2.txt = NULL;
469
470 switch ((int)*op) {
471 case (int)comma:
472 if (pop_obj(&o2) && pop_obj(&o1));
473 else if (REAL_ERROR) break;
474 check_delete(&o1);
475 p=&o2;
476 ret=1;
477 break;
478 case (int)eq:
479 if (pop_obj(&o2) && pop_obj(&o1));
480 else if (REAL_ERROR) break;
481
482 if (o2.type==TYPE_NUM_VAR) {
483 o2.num = *VAR[o2.num].num;
484 o2.type = TYPE_NUM;
485 }
486
487 if (o1.type==TYPE_NUM_VAR && o2.type==TYPE_NUM) {
488 *VAR[o1.num].num = o2.num;
489 p=&o2;
490 ret=1;
491 }
492 else if (o1.type==TYPE_TXT_VAR &&
493 (o2.type==TYPE_TXT || o2.type==TYPE_TXT_VAR)) {
494
495 if (o2.type==TYPE_TXT_VAR) {
496 o2.txt = ptrdup(*VAR[o2.num].str);
497 if (REAL_ERROR) break;
498 o2.type=TYPE_TXT;
499 }
500
501 *VAR[o1.num].str = ptrcpy(*VAR[o1.num].str, o2.txt);
502 if (REAL_ERROR) break;
503 p=&o2;
504 ret=1;
505 }
506 else
507 error=SYNTAX_ERROR;
508 break;
509 case (int)or_or_eq:
510 case (int)xor_xor_eq:
511 case (int)and_and_eq:
512 case (int)or_eq:
513 case (int)xor_eq:
514 case (int)and_eq:
515 case (int)lshift_eq:
516 case (int)rshift_eq:
517 case (int)plus_eq:
518 case (int)minus_eq:
519 case (int)times_eq:
520 case (int)div_eq:
521 case (int)ampersand_eq:
522 if (pop_obj(&o2) && pop_obj(&o1));
523 else if (REAL_ERROR) break;
524
525 if (o2.type==TYPE_NUM_VAR) {
526 o2.num = *VAR[o2.num].num;
527 o2.type = TYPE_NUM;
528 }
529
530 if (o1.type==TYPE_NUM_VAR && o2.type==TYPE_NUM) {
531 l=VAR[o1.num].num;
532
533 switch ((int)*op) {
534 case (int)or_or_eq: if ( o2.num) *l = 1; else *l = !!*l; break;
535 case (int)xor_xor_eq:if ( o2.num) *l = !*l; else *l = !!*l; break;
536 case (int)and_and_eq:if (!o2.num) *l = 0; else *l = !!*l; break;
537 case (int)or_eq: *l |= o2.num; break;
538 case (int)xor_eq: *l ^= o2.num; break;
539 case (int)and_eq: *l &= o2.num; break;
540 case (int)lshift_eq: *l <<= o2.num; break;
541 case (int)rshift_eq: *l >>= o2.num; break;
542 case (int)plus_eq: *l += o2.num; break;
543 case (int)minus_eq: *l -= o2.num; break;
544 case (int)times_eq: *l *= o2.num; break;
545 case (int)div_eq: *l /= o2.num; break;
546 case (int)ampersand_eq:
547 if ((*l %= o2.num) < 0) *l += o2.num; break;
548 }
549 o2.num=*l;
550 p=&o2;
551 ret=1;
552 }
553 else if (*op==plus_eq && o1.type==TYPE_TXT_VAR &&
554 (o2.type==TYPE_TXT || o2.type==TYPE_TXT_VAR)) {
555
556 if (o2.type==TYPE_TXT)
557 src=o2.txt;
558 else
559 src=*VAR[o2.num].str;
560
561 *VAR[o1.num].str = ptrcat(*VAR[o1.num].str, src);
562 check_delete(&o2);
563
564 dst = ptrdup(*VAR[o1.num].str);
565 if (REAL_ERROR) break;
566
567 o1.type=TYPE_TXT;
568 o1.txt=dst;
569 p=&o1;
570 ret=1;
571 }
572 else if (*op==times_eq && o1.type==TYPE_TXT_VAR &&
573 (o2.type==TYPE_NUM || o2.type==TYPE_NUM_VAR)) {
574
575 if (o2.type==TYPE_NUM_VAR) {
576 o2.num = *VAR[o2.num].num;
577 o2.type = TYPE_NUM;
578 }
579
580 if (o2.num < 0)
581 error = OUT_RANGE_ERROR;
582 else if (o2.num == 0)
583 ptrzero(*VAR[o1.num].str);
584 else if (o2.num == 1)
585 ;
586 else if (*VAR[o1.num].str && (delta = ptrlen(*VAR[o1.num].str))) {
587 long n;
588 *VAR[o1.num].str = ptrsetlen(*VAR[o1.num].str, delta*o2.num);
589 tmp = ptrdata(*VAR[o1.num].str);
590 for (n = 1; !error && n<o2.num; n++)
591 memcpy(tmp+n*delta, tmp, delta);
592 }
593
594 check_delete(&o2);
595 dst = ptrdup(*VAR[o1.num].str);
596 if (REAL_ERROR) break;
597
598 o1.type=TYPE_TXT;
599 o1.txt=dst;
600 p=&o1;
601 ret=1;
602 }
603 else
604 error=SYNTAX_ERROR;
605 break;
606 case (int)or_or:
607 case (int)xor_xor:
608 case (int)and_and:
609 case (int)or:
610 case (int)xor:
611 case (int)and:
612 case (int)less:
613 case (int)less_eq:
614 case (int)greater:
615 case (int)greater_eq:
616 case (int)eq_eq:
617 case (int)not_eq:
618 case (int)lshift:
619 case (int)rshift:
620 case (int)minus:
621 case (int)plus:
622 case (int)times:
623 case (int)division:
624 case (int)ampersand:
625 if (pop_obj(&o2) && pop_obj(&o1));
626 else if (REAL_ERROR) break;
627
628 if (o1.type==TYPE_NUM_VAR) {
629 o1.num = *VAR[o1.num].num;
630 o1.type = TYPE_NUM;
631 }
632 if (o2.type==TYPE_NUM_VAR) {
633 o2.num = *VAR[o2.num].num;
634 o2.type = TYPE_NUM;
635 }
636
637 if (o1.type==TYPE_NUM && o2.type==TYPE_NUM) {
638 if (!o2.num &&
639 (*op==division || *op==ampersand)) {
640 error=DIV_BY_ZERO_ERROR;
641 break;
642 }
643
644 switch ((int)*op) {
645 case (int)less: o1.num = o1.num < o2.num ? 1 : 0; break;
646 case (int)less_eq: o1.num = o1.num <= o2.num ? 1 : 0; break;
647 case (int)greater: o1.num = o1.num > o2.num ? 1 : 0; break;
648 case (int)greater_eq:o1.num = o1.num >= o2.num ? 1 : 0; break;
649 case (int)eq_eq: o1.num = o1.num == o2.num ? 1 : 0; break;
650 case (int)not_eq: o1.num = o1.num != o2.num ? 1 : 0; break;
651 case (int)or_or: o1.num = o1.num || o2.num; break;
652 case (int)xor_xor:if (o2.num) o1.num = !o1.num; break;
653 case (int)and_and: o1.num = o1.num && o2.num; break;
654 case (int)or: o1.num |= o2.num; break;
655 case (int)xor: o1.num ^= o2.num; break;
656 case (int)and: o1.num &= o2.num; break;
657 case (int)lshift: o1.num <<= o2.num; break;
658 case (int)rshift: o1.num >>= o2.num; break;
659 case (int)minus: o1.num -= o2.num; break;
660 case (int)plus: o1.num += o2.num; break;
661 case (int)times: o1.num *= o2.num; break;
662 case (int)division:o1.num /= o2.num; break;
663 case (int)ampersand:
664 if ((o1.num %= o2.num) < 0) o1.num += o2.num; break;
665 }
666
667 p=&o1;
668 ret=1;
669 }
670 else if ((o1.type==TYPE_TXT || o1.type==TYPE_TXT_VAR) &&
671 (o2.type==TYPE_TXT || o2.type==TYPE_TXT_VAR)) {
672
673 if (o1.type==TYPE_TXT_VAR) {
674 o1.txt = ptrdup(*VAR[o1.num].str);
675 o1.type = TYPE_TXT; /* not a var anymore */
676 if (REAL_ERROR) break;
677 }
678 dst = o1.txt;
679 if (o2.type==TYPE_TXT)
680 src=o2.txt;
681 else
682 src=*VAR[o2.num].str;
683
684 if (*op == plus) {
685 dst = ptrcat(dst, src);
686 o1.type = TYPE_TXT;
687 } else {
688 o1.num = ptrcmp(dst, src);
689 switch ((int)*op) {
690 case (int)minus: break;
691 case (int)less: o1.num = o1.num < 0; break;
692 case (int)less_eq: o1.num = o1.num <= 0; break;
693 case (int)greater: o1.num = o1.num > 0; break;
694 case (int)greater_eq: o1.num = o1.num >= 0; break;
695 case (int)eq_eq: o1.num = o1.num == 0; break;
696 case (int)not_eq: o1.num = o1.num != 0; break;
697 default:
698 error=SYNTAX_ERROR;
699 p=NULL; ret=0; break;
700 }
701 check_delete(&o1);
702 /* moved here because it interfered with allowing the dst ptr from
703 * being freed, casing a very tiny memory leak */
704 o1.type = TYPE_NUM;
705 }
706 check_delete(&o2);
707 if (!REAL_ERROR) {
708 o1.txt = dst;
709 p=&o1;
710 ret=1;
711 }
712 }
713 else if (*op==times
714 && (o1.type==TYPE_TXT_VAR || o1.type==TYPE_TXT)
715 && o2.type==TYPE_NUM) {
716
717 if (o2.num > 0 && o1.type==TYPE_TXT_VAR) {
718 o1.txt = ptrdup(*VAR[o1.num].str);
719 if (REAL_ERROR) break;
720 }
721 dst = o1.txt;
722
723 if (o2.num < 0)
724 error = OUT_RANGE_ERROR;
725 else if (o2.num == 0)
726 ptrzero(dst);
727 else if (o2.num == 1)
728 ;
729 else if (dst && (delta = ptrlen(dst))) {
730 long n;
731 dst = ptrsetlen(dst, delta*o2.num);
732 tmp = ptrdata(dst);
733 for (n = 1; !error && n<o2.num; n++)
734 memcpy(tmp+n*delta, tmp, delta);
735 }
736 check_delete(&o2);
737 if (REAL_ERROR) break;
738
739 o1.type=TYPE_TXT;
740 o1.txt=dst;
741 p=&o1;
742 ret=1;
743 }
744 else
745 error=SYNTAX_ERROR;
746 break;
747 case (int)colon_less:
748 case (int)colon_greater:
749 case (int)less_colon:
750 case (int)greater_colon:
751 case (int)colon:
752 case (int)point_less:
753 case (int)point_greater:
754 case (int)less_point:
755 case (int)greater_point:
756 case (int)point:
757 if (pop_obj(&o2) && pop_obj(&o1));
758 else if (REAL_ERROR) break;
759
760 if (o2.type==TYPE_NUM_VAR) {
761 o2.num = *VAR[o2.num].num;
762 o2.type = TYPE_NUM;
763 }
764
765 if ((o1.type!=TYPE_TXT_VAR && o1.type!=TYPE_TXT) || o2.type!=TYPE_NUM) {
766 error=SYNTAX_ERROR;
767 break;
768 }
769
770 if (o2.num<=0) {
771 error=OUT_RANGE_ERROR;
772 break;
773 }
774
775 if (o1.type==TYPE_TXT_VAR) {
776 o1.type=TYPE_TXT;
777 o1.txt=dst=NULL;
778 src=start=*VAR[o1.num].str;
779 }
780 else {
781 /* Potentially dangerous: src and dst are overlapping */
782 src=dst=start=o1.txt;
783 danger=1;
784 }
785
786 if (!src) {
787 /* src == empty string. just return it */
788 check_delete(&o2);
789 o1.txt = src;
790 if (!REAL_ERROR)
791 p=&o1; ret=1;
792 break;
793 }
794
795 srclen = ptrlen(src);
796 ssrc = ptrdata(src);
797
798 switch ((int)*op) {
799 case (int)colon_less:
800 while (o2.num && srclen) {
801 /* skip span of multiple word delimeters */
802 while (srclen && memchr(DELIM, *ssrc, DELIM_LEN))
803 srclen--, ssrc++, j++;
804 /* skip whole words */
805 if (srclen && (tmp = memchrs(ssrc, srclen, DELIM, DELIM_LEN)))
806 i=tmp-ssrc, o2.num--, ssrc+=i, j+=i, srclen-=i;
807 else break;
808 }
809
810 if (o2.num) { /* end of valid string before the n-th word */
811 if (danger)
812 ;
813 else
814 dst = ptrcpy(dst, start);
815 } else {
816 if (danger)
817 ptrtrunc(dst, j);
818 else
819 dst = ptrmcpy(dst, ptrdata(start), j);
820 }
821 break;
822 case (int)colon:
823 case (int)colon_greater:
824 o2.num--;
825 /* skip span of multiple word delimeters */
826 while (srclen && memchr(DELIM, *ssrc, DELIM_LEN))
827 srclen--, ssrc++;
828 while (o2.num && srclen) {
829 /* skip whole words */
830 if (srclen && (tmp = memchrs(ssrc, srclen, DELIM, DELIM_LEN))) {
831 i=tmp-ssrc, o2.num--, ssrc+=i, srclen-=i;
832 /* skip span of multiple word delimeters */
833 while (srclen && memchr(DELIM, *ssrc, DELIM_LEN))
834 srclen--, ssrc++;
835 } else break;
836 }
837
838 if (o2.num) /* end of valid string before the n-th word */
839 ptrzero(dst);
840 else {
841 if (*op==colon &&
842 (tmp = memchrs(ssrc, srclen, DELIM, DELIM_LEN))) {
843 dst = ptrmcpy(dst, ssrc, tmp-ssrc);
844 }
845 else
846 dst = ptrmcpy(dst, ssrc, srclen);
847 }
848 break;
849 case (int)less_colon:
850 o2.num--;
851 while (o2.num && srclen) {
852 /* skip span of multiple word delimeters */
853 while (srclen && memchr(DELIM, ssrc[srclen], DELIM_LEN))
854 srclen--;
855 /* skip whole words */
856 if (srclen && (tmp=memrchrs(ssrc, srclen, DELIM, DELIM_LEN)))
857 o2.num--, srclen=tmp-ssrc;
858 else break;
859 }
860
861 if (o2.num) /* end of valid string before the n-th word */
862 ptrzero(dst);
863 else
864 dst = ptrmcpy(dst, ssrc, srclen);
865 break;
866 case (int)greater_colon:
867 while (o2.num && srclen) {
868 /* skip span of multiple word delimeters */
869 while (srclen && memchr(DELIM, ssrc[srclen], DELIM_LEN))
870 srclen--;
871 /* skip whole words */
872 if (srclen && (tmp=memrchrs(ssrc, srclen, DELIM, DELIM_LEN)))
873 o2.num--, srclen=tmp-ssrc;
874 else break;
875 }
876
877 if (o2.num) /* end of valid string before the n-th word */
878 dst = ptrcpy(dst, start);
879 else
880 dst = ptrmcpy(dst, ssrc+srclen+1,
881 ptrlen(start) - (ssrc+srclen+1 - ptrdata(start)));
882 break;
883 case (int)point:
884 j = o2.num <= srclen ? o2.num-1 : srclen;
885 dst = ptrmcpy(dst, ssrc+j, 1);
886 break;
887 case (int)point_less:
888 j = o2.num < srclen ? o2.num : srclen;
889 if (danger)
890 ptrtrunc(dst, j);
891 else
892 dst = ptrmcpy(dst, ssrc, j);
893 break;
894 case (int)less_point:
895 j = srclen-o2.num+1;
896 if (j < 0)
897 j = 0;
898 if (danger)
899 ptrtrunc(dst, j);
900 else
901 dst = ptrmcpy(dst, ssrc, j);
902 break;
903 case (int)point_greater:
904 j = o2.num-1 < srclen ? o2.num-1 : srclen;
905 dst = ptrmcpy(dst, ssrc+j, srclen-j);
906 break;
907 case (int)greater_point:
908 j = srclen-o2.num;
909 if (j < 0)
910 j = 0;
911 dst = ptrmcpy(dst, ssrc+j, srclen-j);
912 break;
913 }
914 check_delete(&o2);
915 o1.txt = dst;
916 if (!REAL_ERROR)
917 p=&o1; ret=1;
918 break;
919 case (int)colon_question:
920 case (int)point_question:
921 if (pop_obj(&o1));
922 else if (REAL_ERROR) break;
923
924 if (o1.type==TYPE_TXT)
925 src=o1.txt;
926 else if (o1.type==TYPE_TXT_VAR)
927 src=*VAR[o1.num].str;
928 else {
929 error=SYNTAX_ERROR;
930 break;
931 }
932 if (!src) {
933 /* empty string. return 0 */
934 check_delete(&o1);
935 o1.type=TYPE_NUM;
936 o1.num =0;
937 p=&o1;
938 ret=1;
939 break;
940 }
941
942 ssrc = ptrdata(src);
943 srclen = ptrlen(src);
944
945 if (*op==colon_question) {
946 o1.num = 0;
947 /* skip span of multiple word delimeters */
948 while (srclen && memchr(DELIM, *ssrc, DELIM_LEN))
949 ssrc++, srclen--;
950 while (srclen) {
951 /* skip whole words */
952 if (srclen && (tmp=memchrs(ssrc, srclen, DELIM, DELIM_LEN))) {
953 i=tmp-ssrc, o1.num++, ssrc+=i, srclen-=i;
954 /* skip span of multiple word delimeters */
955 while (srclen && memchr(DELIM, *ssrc, DELIM_LEN))
956 srclen--, ssrc++;
957 } else {
958 srclen=0;
959 o1.num++;
960 }
961 }
962 }
963 else
964 o1.num=srclen;
965
966 check_delete(&o1);
967 o1.type=TYPE_NUM;
968 p=&o1;
969 ret=1;
970 break;
971 case (int)question:
972 if (pop_obj(&o2) && pop_obj(&o1));
973 else if (REAL_ERROR) break;
974
975 if (o1.type==TYPE_TXT)
976 src = o1.txt;
977 else if (o1.type==TYPE_TXT_VAR)
978 src = *VAR[o1.num].str;
979 else
980 error = SYNTAX_ERROR;
981
982 if (o2.type==TYPE_TXT)
983 dst = o2.txt;
984 else if (o2.type==TYPE_TXT_VAR)
985 dst = *VAR[o2.num].str;
986 else
987 error = SYNTAX_ERROR;
988
989 if (!error) {
990 if ((ssrc = ptrfind(src, dst)))
991 i = (int)(ssrc - ptrdata(src)) + 1;
992 else
993 i = 0;
994 o1.type = TYPE_NUM;
995 o1.num = i;
996 p=&o1; ret=1;
997 }
998 check_delete(&o1);
999 check_delete(&o2);
1000 break;
1001 case (int)null:
1002 case (int)another_null:
1003 if (pop_obj(&o2) && pop_obj(&o1));
1004 else if (REAL_ERROR) break;
1005
1006 check_delete(&o1);
1007 check_delete(&o2);
1008
1009 o1.type=0, o1.num=0, o1.txt=NULL;
1010
1011 p=&o1;
1012 ret=1;
1013 break;
1014 case (int)left_paren:
1015 error=MISSING_PAREN_ERROR;
1016 break;
1017 case (int)right_paren:
1018 if (pop_op(op));
1019 else if (REAL_ERROR) break;
1020
1021 if (*op!=left_paren)
1022 error=MISMATCH_PAREN_ERROR;
1023 else
1024 ret=1;
1025
1026 break;
1027 case (int)_random_:
1028 #ifdef NO_RANDOM
1029 error = NOT_SUPPORTED_ERROR;
1030 break;
1031 #endif
1032 case (int)pre_plus:
1033 case (int)pre_minus:
1034 case (int)not:
1035 case (int)tilde:
1036
1037 if (pop_obj(&o1));
1038 else if (REAL_ERROR) break;
1039
1040 if (o1.type==TYPE_NUM_VAR) {
1041 o1.num = *VAR[o1.num].num;
1042 o1.type = TYPE_NUM;
1043 }
1044 if (o1.type==TYPE_NUM) {
1045 if (*op==pre_minus)
1046 o1.num=-o1.num;
1047 else if (*op==not)
1048 o1.num=!o1.num;
1049 else if (*op==tilde)
1050 o1.num=~o1.num;
1051 #ifndef NO_RANDOM
1052 else if (*op==_random_) {
1053 if (o1.num <= 0) {
1054 error=OUT_RANGE_ERROR;
1055 break;
1056 } else {
1057 delta = LONG_MAX - LONG_MAX % o1.num;
1058 while (rnd = get_random(), rnd > delta);
1059 /* skip numbers that would alterate distribution */
1060 o1.num = rnd / (delta / o1.num);
1061 }
1062 }
1063 #endif
1064 p=&o1;
1065 ret=1;
1066 }
1067 else
1068 error=SYNTAX_ERROR;
1069 break;
1070 case (int)_attr_:
1071 if (pop_obj(&o1));
1072 else if (REAL_ERROR) break;
1073
1074 if (o1.type==TYPE_TXT_VAR) {
1075 o1.txt = ptrdup(*VAR[o1.num].str);
1076 if (REAL_ERROR) break;
1077 o1.type = TYPE_TXT;
1078 }
1079
1080 if (o1.type==TYPE_TXT) {
1081 char dummy[CAPLEN]; /* just because attr_string must write somewhere */
1082
1083 if (o1.txt)
1084 i = parse_attributes(ptrdata(o1.txt));
1085 else
1086 i = NOATTRCODE;
1087 if (i == -1)
1088 error=BAD_ATTR_ERROR;
1089 else {
1090 o1.txt = ptrsetlen(o1.txt, CAPLEN);
1091 if (REAL_ERROR) break;
1092 attr_string(i, ptrdata(o1.txt), dummy);
1093 ptrtrunc(o1.txt, strlen(ptrdata(o1.txt)));
1094 p=&o1;
1095 ret = 1;
1096 }
1097 } else
1098 error=NO_STRING_ERROR;
1099 break;
1100
1101 case (int)star:
1102 case (int)print:
1103 if (pop_obj(&o1));
1104 else if (REAL_ERROR) break;
1105
1106 if (o1.type==TYPE_NUM_VAR)
1107 o1.num = *VAR[o1.num].num;
1108 else if (o1.type==TYPE_TXT_VAR)
1109 o1.txt = *VAR[o1.num].str;
1110
1111 if (o1.type==TYPE_NUM || o1.type==TYPE_NUM_VAR) {
1112 o1.txt = NULL;
1113 if (*op==print) {
1114 char buf[LONGLEN];
1115 sprintf(buf, "%ld", o1.num);
1116 o1.txt = ptrmcpy(o1.txt, buf, strlen(buf));
1117 } else {
1118 char buf = (char)o1.num;
1119 o1.txt = ptrmcpy(o1.txt, &buf, 1);
1120 }
1121 if (REAL_ERROR) break;
1122 o1.type = TYPE_TXT;
1123 p=&o1; ret=1;
1124 }
1125 else if (o1.type==TYPE_TXT || o1.type==TYPE_TXT_VAR) {
1126 if (*op==print) {
1127 if (o1.txt && ptrlen(o1.txt))
1128 o1.num = atol(ptrdata(o1.txt));
1129 else
1130 o1.num = 0;
1131 } else {
1132 if (o1.txt && ptrlen(o1.txt))
1133 o1.num = (long)(byte)*ptrdata(o1.txt);
1134 else
1135 o1.num = 0;
1136 }
1137 check_delete(&o1);
1138 o1.type = TYPE_NUM;
1139 p=&o1; ret=1;
1140 }
1141 else
1142 error=SYNTAX_ERROR;
1143 break;
1144 case (int)pre_plus_plus:
1145 case (int)post_plus_plus:
1146 case (int)pre_minus_minus:
1147 case (int)post_minus_minus:
1148 if (pop_obj(&o1));
1149 else if (REAL_ERROR) break;
1150
1151 if (o1.type==TYPE_NUM_VAR) {
1152 l=VAR[o1.num].num;
1153 o1.type=TYPE_NUM;
1154
1155 if (*op==pre_plus_plus)
1156 o1.num=++*l;
1157 else if (*op==post_plus_plus)
1158 o1.num=(*l)++;
1159 else if (*op==pre_minus_minus)
1160 o1.num=--*l;
1161 else
1162 o1.num=(*l)--;
1163
1164 p=&o1;
1165 ret=1;
1166 }
1167 else
1168 error=SYNTAX_ERROR;
1169 break;
1170 case (int)a_circle:
1171 case (int)dollar:
1172 if (pop_obj(&o1));
1173 else if (REAL_ERROR) break;
1174
1175 if (*op == dollar)
1176 delta = 1;
1177 else
1178 delta = 0;
1179
1180 if (o1.type==TYPE_NUM_VAR) {
1181 o1.type=TYPE_NUM;
1182 o1.num=*VAR[o1.num].num;
1183 }
1184
1185 if (o1.type==TYPE_NUM) {
1186 if (o1.num<-NUMVAR || o1.num>=NUMPARAM) {
1187 error=OUT_RANGE_ERROR;
1188 break;
1189 }
1190 o1.type= delta ? TYPE_TXT_VAR : TYPE_NUM_VAR;
1191 p=&o1;
1192 ret=1;
1193 } else {
1194 varnode *named_var;
1195 char c;
1196
1197 if (o1.type==TYPE_TXT_VAR)
1198 o1.txt = *VAR[o1.num].str;
1199 else if (o1.type!=TYPE_TXT) {
1200 error=SYNTAX_ERROR;
1201 break;
1202 }
1203
1204 if (o1.txt && (tmp=ptrdata(o1.txt)) &&
1205 ((c=*tmp) == '_' || isalpha(c))) {
1206 tmp++;
1207 while ((c=*tmp) == '_' || isalnum(c))
1208 tmp++;
1209 }
1210 if (!o1.txt || *tmp) {
1211 error=INVALID_NAME_ERROR;
1212 break;
1213 }
1214
1215 if (!(named_var = *lookup_varnode(ptrdata(o1.txt), delta))) {
1216 named_var = add_varnode(ptrdata(o1.txt), delta);
1217 if (REAL_ERROR)
1218 break;
1219 if (opt_info) {
1220 PRINTF("#new variable: %c%s\n", delta
1221 ? '$' : '@', ptrdata(o1.txt));
1222 }
1223 }
1224 o1.type= delta ? TYPE_TXT_VAR : TYPE_NUM_VAR;
1225 p=&o1;
1226 ret=1;
1227 }
1228 break;
1229 case (int)pre_null:
1230 case (int)post_null:
1231 ret=1;
1232 break;
1233 default:
1234 break;
1235 }
1236
1237 if (REAL_ERROR) {
1238 check_delete(&o2);
1239 check_delete(&o1);
1240 }
1241
1242 if (!REAL_ERROR) {
1243 if (!ret)
1244 error=NOT_DONE_ERROR;
1245 else if (p) {
1246 if (push_obj(p))
1247 ;
1248 else
1249 check_delete(p);
1250 }
1251 }
1252
1253 if (REAL_ERROR)
1254 return 0;
1255
1256 return ret;
1257 }
1258
__P2(operator *,op1,operator *,op2)1259 static int whichfirst __P2 (operator *,op1, operator *,op2)
1260 {
1261 int p1, p2;
1262
1263 p1=op_list[*op1].priority;
1264 p2=op_list[*op2].priority;
1265 if (p1!=p2)
1266 return p1>p2 ? -1 : 1;
1267
1268 p1 = op_list[*op1].assoc == LEFT;
1269 return p1 ? -1 : 1;
1270 }
1271
__P1(operator *,op)1272 static int compare_and_unload __P1 (operator *,op)
1273 {
1274 int first=0;
1275 operator new;
1276
1277 if (REAL_ERROR || stk.curr_op<0)
1278 return 1;
1279
1280 while (stk.curr_op>=0 && pop_op(&new) && !REAL_ERROR &&
1281 (first = whichfirst(&new, op)) == -1 &&
1282 (first = 0, exe_op(&new))
1283 );
1284
1285 if (!REAL_ERROR) {
1286 if (!first)
1287 return 1;
1288 else
1289 return push_op(&new);
1290 } else
1291 return 0;
1292 }
1293
__P1(int,mindepth)1294 static int _eval __P1 (int,mindepth)
1295 {
1296 operator op;
1297 object obj;
1298 char endreached = 0;
1299
1300 for (;;) {
1301 memzero(&obj, sizeof(obj));
1302
1303 while (*line==' ') line++;
1304 if (!*line || *line == CMDSEP)
1305 endreached = 1;
1306
1307 while (check_operator(LEFT, &op, mindepth) && push_op(&op) &&
1308 !endreached) {
1309
1310 if (error) return 0;
1311 while (*line==' ') line++;
1312 if (!*line || *line == CMDSEP)
1313 endreached = 1;
1314 }
1315
1316 if (!endreached && check_object(&obj) && push_obj(&obj));
1317 else if (error) return 0;
1318
1319 while (*line==' ') line++;
1320 if (!*line || *line == CMDSEP)
1321 endreached = 1;
1322
1323 while (check_operator(RIGHT, &op, mindepth) && compare_and_unload(&op) &&
1324 exe_op(&op) && depth>=mindepth && !endreached) {
1325
1326 if (error) return 0;
1327 while (*line==' ')
1328 line++;
1329 if (!*line || *line == CMDSEP)
1330 endreached = 1;
1331 }
1332 if (error) return 0;
1333
1334 if (endreached || depth < mindepth)
1335 break;
1336
1337 if (check_operator(BINARY, &op, mindepth) &&
1338 compare_and_unload(&op) && push_op(&op));
1339 else if (error) return 0;
1340 }
1341 return 1;
1342 }
1343
__P3(long *,lres,ptr *,pres,char **,what)1344 int eval_any __P3 (long *,lres, ptr *,pres, char **,what)
1345 {
1346 int printmode;
1347 long val;
1348 ptr txt;
1349 object res;
1350
1351 if (pres)
1352 printmode = PRINT_AS_PTR;
1353 else if (lres)
1354 printmode = PRINT_AS_LONG;
1355 else
1356 printmode = PRINT_NOTHING;
1357
1358 error=0;
1359 stk.curr_obj=stk.curr_op=-1;
1360 line = *what;
1361
1362 depth = 0;
1363 (void)_eval(0);
1364
1365 if (!error)
1366 (void)pop_obj(&res);
1367 if (error) {
1368 if (opt_debug) {
1369 PRINTF("#result not available\n");
1370 }
1371 } else if (printmode!=PRINT_NOTHING || opt_debug) {
1372 if (res.type==TYPE_NUM || res.type==TYPE_NUM_VAR) {
1373
1374 val = res.type==TYPE_NUM ? res.num : *VAR[res.num].num;
1375
1376 if (printmode==PRINT_AS_PTR) {
1377 *pres = ptrsetlen(*pres, LONGLEN);
1378 if (!MEM_ERROR) {
1379 sprintf(ptrdata(*pres), "%ld", val);
1380 (*pres)->len = strlen(ptrdata(*pres));
1381 }
1382 } else if (printmode==PRINT_AS_LONG)
1383 *lres=val;
1384
1385 if (opt_debug) {
1386 if (error) {
1387 PRINTF("#result not available\n");
1388 } else {
1389 PRINTF("#result: %ld\n", val);
1390 }
1391 }
1392 } else {
1393 txt = res.type==TYPE_TXT ? res.txt : *VAR[res.num].str;
1394 if (printmode==PRINT_AS_PTR) {
1395 if (txt && *ptrdata(txt)) {
1396 if (res.type == TYPE_TXT)
1397 /* shortcut! */
1398 *pres = txt;
1399 else
1400 *pres = ptrcpy(*pres, txt);
1401 } else
1402 ptrzero(*pres);
1403 }
1404 if (opt_debug) {
1405 if (error) {
1406 PRINTF("#result not available\n");
1407 } else if (txt && *ptrdata(txt)) {
1408 PRINTF("#result: %s\n", ptrdata(txt));
1409 } else {
1410 PRINTF("#result empty\n");
1411 }
1412 }
1413 }
1414 }
1415 *what=line;
1416
1417 if (!error) {
1418 if (printmode==PRINT_AS_PTR && res.type == TYPE_TXT
1419 && res.txt && ptrdata(res.txt))
1420 /* shortcut! */
1421 ;
1422 else
1423 check_delete(&res);
1424 } else {
1425 while (stk.curr_obj>=0) {
1426 pop_obj(&res);
1427 check_delete(&res);
1428 }
1429 res.type = 0;
1430 }
1431
1432 if (res.type==TYPE_TXT_VAR)
1433 res.type = TYPE_TXT;
1434 else if (res.type==TYPE_NUM_VAR)
1435 res.type = TYPE_NUM;
1436
1437 return res.type;
1438 }
1439
__P2(ptr *,res,char **,what)1440 int evalp __P2 (ptr *,res, char **,what)
1441 {
1442 return eval_any((long *)0, res, what);
1443 }
1444
__P2(long *,res,char **,what)1445 int evall __P2 (long *,res, char **,what)
1446 {
1447 return eval_any(res, (ptr *)0, what);
1448 }
1449
__P1(char **,what)1450 int evaln __P1 (char **,what)
1451 {
1452 return eval_any((long *)0, (ptr *)0, what);
1453 }
1454
1455