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